diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6171687e..87dfc80e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,7 +6,9 @@ version: 2 updates: - package-ecosystem: npm - directory: '/' # Location of package manifests + directories: + - / + - packages/* schedule: interval: 'monthly' - package-ecosystem: 'github-actions' diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 89f1fbd1..e80893d5 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -12,6 +12,8 @@ on: jobs: publish: + # Only run if it's the upstream repository, not forks + if: github.repository == 'wxt-dev/wxt' runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5dc10afd..4ab2d2c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,7 @@ on: - module-solid - module-svelte - module-vue + - unocss - wxt jobs: diff --git a/.github/workflows/sync-releases.yml b/.github/workflows/sync-releases.yml index 09e302c8..4287f089 100644 --- a/.github/workflows/sync-releases.yml +++ b/.github/workflows/sync-releases.yml @@ -12,6 +12,8 @@ on: - module-vue - module-svelte - module-solid + - auto-icons + - i18n jobs: sync: diff --git a/.github/workflows/vhs.yml b/.github/workflows/vhs.yml index 13936141..1d822165 100644 --- a/.github/workflows/vhs.yml +++ b/.github/workflows/vhs.yml @@ -20,7 +20,7 @@ jobs: - uses: charmbracelet/vhs-action@v2.1.0 with: path: 'docs/tapes/init-demo.tape' - - uses: stefanzweifel/git-auto-commit-action@v4 + - uses: stefanzweifel/git-auto-commit-action@v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 58eb4541..fbe6fdc3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -Everyone is welcome to contribute to WXT! +Everyone is welcome to contribute to **WXT**! If you are changing the docs or fixing a bug, feel free to fork and open a PR. @@ -139,7 +139,7 @@ Releases are done with GitHub actions: Use [`taze`](https://www.npmjs.com/package/taze) to upgrade dependencies throughout the entire monorepo. -```ts +```sh pnpm dlx taze -r ``` diff --git a/README.md b/README.md index 5daaef45..295b4d77 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@

- WXT Logo + WXT Logo WXT

- npm + npm version - npm + downloads - NPM + license | MIT - Codecov + coverage

@@ -43,10 +43,21 @@ https://github.com/wxt-dev/wxt/assets/10101283/4d678939-1bdb-495c-9c36-3aa281d84 Bootstrap a new project: + + ```sh -pnpm dlx wxt@latest init +# npm +npx wxt@latest init + +# pnpm +pnpm dlx wxt@latest init + +# bun +bunx wxt@latest init ``` + + Or see the [installation guide](https://wxt.dev/guide/installation.html) to get started with WXT. ## Features @@ -59,13 +70,20 @@ 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 ## Contributors + + +Published under the [MIT](https://github.com/wxt-dev/wxt/blob/main/LICENSE) license. +Made by [@aklinker1](https://github.com/aklinker1) and [community](https://github.com/wxt-dev/wxt/graphs/contributors) πŸ’› +

- + + + 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/components/UsingWxtSection.vue b/docs/.vitepress/components/UsingWxtSection.vue index 8694d27c..610f4e02 100644 --- a/docs/.vitepress/components/UsingWxtSection.vue +++ b/docs/.vitepress/components/UsingWxtSection.vue @@ -39,6 +39,17 @@ const chromeExtensionIds = [ 'lnhejcpclabmbgpiiomjbhalblnnbffg', // 1Proompt 'fonflmjnjbkigocpoommgmhljdpljain', // NiceTab - https://github.com/web-dahuyou/NiceTab 'fcffekbnfcfdemeekijbbmgmkognnmkd', // Draftly for LinkedIn + 'nkndldfehcidpejfkokbeghpnlbppdmo', // YouTube Summarized - Summarize any YouTube video + 'dbichmdlbjdeplpkhcejgkakobjbjalc', // η€Ύεͺ’εŠ©ζ‰‹ - https://github.com/iszhouhua/social-media-copilot + 'opepfpjeogkbgeigkbepobceinnfmjdd', // Dofollow Links for SEO + 'pdnenlnelpdomajfejgapbdpmjkfpjkp', // ChatGPT Writer: Use AI on Any Site (GPT-4o, Claude, Gemini, and More) + 'jobnhifpphkgoelnhnopgkdhbdkiadmj', // discord message translator + 'ncokhechhpjgjonhjnlaneglmdkfkcbj', // Habit Tracker app widget for daily habit tracking + 'lnjaiaapbakfhlbjenjkhffcdpoompki', // Catppuccin for GitHub File Explorer Icons + 'cpaedhbidlpnbdfegakhiamfpndhjpgf', // WebChat: Chat with anyone on any website + 'fcphghnknhkimeagdglkljinmpbagone', // YouTube Auto HD + FPS + 'lpomjgbicdemjkgmbnkjncgdebogkhlb', // MultiViewer Companion + 'ggiafipgeeaaahnjamgpjcgkdpanhddg', // Sync Watch - Watch videos together on any site ]; const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds); diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 33a97536..1a575731 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -8,6 +8,11 @@ import { prepareTypedocSidebar, } from './utils/menus'; import { meta, script } from './utils/head'; +import footnote from 'markdown-it-footnote'; +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'; +import { version as unocssVersion } from '../../packages/unocss/package.json'; const title = 'Next-gen Web Extension Framework'; const titleSuffix = ' – WXT'; @@ -43,6 +48,12 @@ export default defineConfig({ }), ], + markdown: { + config: (md) => { + md.use(footnote); + }, + }, + themeConfig: { // https://vitepress.dev/reference/default-theme-config logo: { @@ -64,111 +75,94 @@ 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'), + navItem(`@wxt-dev/unocss β€” ${unocssVersion}`, '/unocss'), + ]), + ]), ], 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/loaders/cli.data.ts b/docs/.vitepress/loaders/cli.data.ts index c99d9484..77327e70 100644 --- a/docs/.vitepress/loaders/cli.data.ts +++ b/docs/.vitepress/loaders/cli.data.ts @@ -1,6 +1,6 @@ -import { resolve, join } from 'node:path'; +import { resolve } from 'node:path'; import consola from 'consola'; -import { execaCommand } from 'execa'; +import spawn from 'nano-spawn'; const cliDir = resolve('packages/wxt/src/cli/commands'); const cliDirGlob = resolve(cliDir, '**'); @@ -37,7 +37,8 @@ export default { }; async function getHelp(command: string): Promise { - const res = await execaCommand(command + ' --help', { + const args = command.split(' '); + const res = await spawn(args[0], [...args.slice(1), '--help'], { cwd: 'packages/wxt', }); return res.stdout; 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 bdaa3b45..353c8b73 100644 Binary files a/docs/assets/init-demo.gif and b/docs/assets/init-demo.gif differ 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 41982076..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 | [], - 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..8e299665 --- /dev/null +++ b/docs/guide/essentials/config/environment-variables.md @@ -0,0 +1,58 @@ +# 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 +.env.[browser] +.env.[browser].local +.env.[mode].[browser] +.env.[mode].[browser].local +``` + +And any environment variables listed inside them will be available at runtime: + +```sh +# .env +WXT_API_KEY=... +``` + +```ts +await fetch(`/some-api?apiKey=${import.meta.env.WXT_API_KEY}`); +``` + +Remember to prefix any environment variables with `WXT_` or `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..2885ef28 --- /dev/null +++ b/docs/guide/essentials/config/hooks.md @@ -0,0 +1,58 @@ +# Hooks + +WXT includes a system that lets you hook into the build process and make changes. + +## Adding Hooks + +The easiest way to add a hook is via the `wxt.config.ts`. 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. The other arguments can be modified by reference to change different parts of the build system. + +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. + +## Execution Order + +Because hooks can be defined in multiple places, including [WXT Modules](/guide/essentials/wxt-modules), the order which they're executed can matter. Hooks are executed in the following order: + +1. NPM modules in the order listed in the [`modules` config](/api/reference/wxt/interfaces/InlineConfig#modules) +2. User modules in [`/modules` folder](/guide/essentials/project-structure), loaded alphabetically +3. Hooks listed in your `wxt.config.ts` + +To see the order for your project, run `wxt prepare --debug` flag and search for the "Hook execution order": + +``` +βš™ Hook execution order: +βš™ 1. wxt:built-in:unimport +βš™ 2. src/modules/auto-icons.ts +βš™ 3. src/modules/example.ts +βš™ 4. src/modules/i18n.ts +βš™ 5. wxt.config.ts > hooks +``` + +Changing execution order is simple: + +- Prefix your user modules with a number (lower numbers are loaded first): + + ```html + πŸ“ modules/ + πŸ“„ 0.my-module.ts + πŸ“„ 1.another-module.ts + ``` +- If you need to run an NPM module after user modules, just make it a user module and prefix the filename with a number! + ```ts + // modules/2.i18n.ts + export { default } from '@wxt-dev/i18n/module'; + ``` 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..2bdd8c8a --- /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.WXT_API_KEY, + skipWelcome: import.meta.env.WXT_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..5db2fda5 --- /dev/null +++ b/docs/guide/essentials/target-different-browsers.md @@ -0,0 +1,77 @@ +# 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 targeted. + +```sh +wxt # same as: wxt -b chrome +wxt -b firefox +wxt -b custom +``` + +During development, if you target Firefox, Firefox will open. All other strings open Chrome by default. To customize which browsers open, see [Set Browser Binaries](/guide/essentials/config/browser-startup#set-browser-binaries). + +Additionally, WXT defines several constants you can use at runtime to detect which browser is in use: + +```ts +if (import.meta.env.BROWSER === 'firefox') { + console.log('Do something only in Firefox builds'); +} +if (import.meta.env.FIREFOX) { + // Shorthand, equivalent to the if-statement above +} +``` + +Read about [Built-in Environment Variables](/guide/essentials/config/environment-variables.html#built-in-environment-variables) for more details. + +## 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 browsers. +::: + +Similar to the browser, you can get the target manifest version at runtime using the [built-in environment variable](/guide/essentials/config/environment-variables.html#built-in-environment-variables): + +```ts +if (import.meta.env.MANIFEST_VERSION === 2) { + console.log('Do something only in MV2 builds'); +} +``` + +## Filtering Entrypoints + +Every entrypoint can be included or excluded when targeting specific browsers via the `include` and `exclude` options. + +Here are some examples: + +- Content script only built when targeting `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..9ec0c43f --- /dev/null +++ b/docs/guide/essentials/wxt-modules.md @@ -0,0 +1,246 @@ +# 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. + +## Execution Order + +Modules are loaded in the same order as hooks are executed. Refer to the [Hooks documentation](/guide/essentials/config/hooks#execution-order) for more details. + +## 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..88080cb6 --- /dev/null +++ b/docs/guide/resources/compare.md @@ -0,0 +1,66 @@ +# 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 | βœ… | βœ… | 🟑 [^j] | +| MV2 Support | βœ… | βœ… | 🟑 [^a] | +| MV3 Support | βœ… | βœ… | 🟑 [^a] | +| Create Extension ZIPs | βœ… | βœ… | ❌ | +| Create Firefox Sources ZIP | βœ… | ❌ | ❌ | +| First-class TypeScript support | βœ… | βœ… | βœ… | +| Entrypoint discovery | βœ… [^b] | βœ… [^b] | ❌ | +| Inline entrypoint config | βœ… | βœ… | ❌ [^i] | +| Auto-imports | βœ… | ❌ | ❌ | +| Reusable module system | βœ… | ❌ | ❌ | +| Supports all frontend frameworks | βœ… | 🟑 [^c] | βœ… | +| Framework specific entrypoints (like `Popup.tsx`) | 🟑 [^d] | βœ… [^e] | ❌ | +| Automated publishing | βœ… | βœ… | ❌ | +| Remote Code Bundling (Google Analytics) | βœ… | βœ… | ❌ | +| Unlisted HTML Pages | βœ… | βœ… | βœ… | +| Unlisted Scripts | βœ… | ❌ | ❌ | +| ESM Content Scripts | ❌ [^l] | ❌ | βœ… | +| Dev Mode | | | | +| `.env` Files | βœ… | βœ… | βœ… | +| Opens browser with extension installed | βœ… | ❌ | ❌ | +| HMR for UIs | βœ… | 🟑 [^f] | βœ… | +| Reload HTML Files on Change | βœ… | 🟑 [^g] | βœ… | +| Reload Content Scripts on Change | βœ… | 🟑 [^g] | βœ… | +| Reload Background on Change | 🟑 [^g] | 🟑 [^g] | 🟑 [^g] | +| Respects Content Script `run_at` | βœ… | βœ… | ❌ [^h] | +| Built-in Wrappers | | | | +| Storage | βœ… | βœ… | ❌ [^k] | +| Messaging | ❌ [^k] | βœ… | ❌ [^k] | +| Content Script UI | βœ… | βœ… | ❌ [^k] | +| I18n | βœ… | ❌ | ❌ | + +[^a]: Either MV2 or MV3, not both. + +[^b]: File based. + +[^c]: Only React, Vue, and Svelte. + +[^d]: `.html`, `.ts`, `.tsx`. + +[^e]: `.html`, `.ts`, `.tsx`, `.vue`, `.svelte`. + +[^f]: React only. + +[^g]: Reloads entire extension. + +[^h]: ESM-style loaders run asynchronously. + +[^i]: Entrypoint options all configured in `manifest.json`. + +[^j]: As of `v2.0.0-beta.23`, but v2 stable hasn't been released yet. + +[^k]: 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. + +[^l]: WIP, moving very slowly. Follow [wxt-dev/wxt#357](https://github.com/wxt-dev/wxt/issues/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 62% rename from docs/get-started/migrate-to-wxt.md rename to docs/guide/resources/migrate.md index d51a3339..8deb49f3 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,19 @@ 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. Replace your [Plasmo tags](https://docs.plasmo.com/framework/workflows/build#with-a-custom-tag) (`--tag`) with [WXT build modes](/guide/essentials/config/build-mode) (`--mode`) +8. 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 +61,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..825f4cad 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,72 @@ # 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.html#build-integrations +/guide/i18n/introduction.html /i18n.html +/guide/i18n/messages-file-format.html /i18n.html#messages-file-format +/guide/i18n/editor-support.html /i18n.html#editor-support +/guide/i18n/installation.html /i18n.html#installation +/guide/i18n/installation /i18n.html#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/docs/unocss.md b/docs/unocss.md new file mode 100644 index 00000000..8e407a35 --- /dev/null +++ b/docs/unocss.md @@ -0,0 +1 @@ + diff --git a/package.json b/package.json index 35783e26..21ea5945 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "engines": { "node": ">=18.20.3" }, - "packageManager": "pnpm@9.6.0", + "packageManager": "pnpm@9.12.0", "scripts": { "check": "check && pnpm -r --sequential run check", "test": "pnpm -r --sequential run test run", @@ -17,31 +17,28 @@ "docs:preview": "pnpm -s docs:gen && vitepress preview docs" }, "devDependencies": { - "@aklinker1/buildc": "^1.1.1", + "@aklinker1/buildc": "^1.1.4", "@aklinker1/check": "^1.4.5", "@types/fs-extra": "^11.0.4", - "@vitest/coverage-v8": "^2.0.4", - "changelogen": "^0.5.5", + "@vitest/coverage-v8": "^2.1.2", + "changelogen": "^0.5.7", "consola": "^3.2.3", - "dependency-graph": "^1.0.0", - "execa": "^9.3.1", "fast-glob": "^3.3.2", "fs-extra": "^11.2.0", - "hasha": "^6.0.0", - "lint-staged": "^15.2.7", - "npm-run-all": "^4.1.5", + "lint-staged": "^15.2.10", + "markdown-it-footnote": "^4.0.0", + "nano-spawn": "^0.1.0", "prettier": "^3.3.3", "simple-git-hooks": "^2.11.1", "tsx": "4.15.7", "typedoc": "^0.25.4", "typedoc-plugin-markdown": "4.0.0-next.23", "typedoc-vitepress-theme": "1.0.0-next.3", - "typescript": "^5.5.4", - "vitepress": "^1.3.1", - "vitest-mock-extended": "^2.0.0", - "vue": "^3.4.34", - "wxt": "workspace:*", - "yaml": "^2.5.0" + "typescript": "^5.6.2", + "vitepress": "^1.3.4", + "vitest-mock-extended": "^2.0.2", + "vue": "^3.5.11", + "wxt": "workspace:*" }, "simple-git-hooks": { "pre-commit": "pnpm lint-staged" @@ -55,11 +52,9 @@ "@algolia/client-search", "search-insights" ] + }, + "patchedDependencies": { + "markdown-it-footnote": "patches/markdown-it-footnote.patch" } - }, - "changelog": { - "excludeAuthors": [ - "aaronklinker1@gmail.com" - ] } } diff --git a/packages/analytics/README.md b/packages/analytics/README.md index fd87e178..f5184e10 100644 --- a/packages/analytics/README.md +++ b/packages/analytics/README.md @@ -4,8 +4,8 @@ Add analytics, like google analytics, to your WXT extension. ## Supported Analytics Providers -- Google Analytics (Measurement Protocol) -- Umami +- [Google Analytics 4 (Measurement Protocol)](#google-analytics-4-measurement-protocol) +- [Umami](#umami) ## Installation @@ -49,7 +49,7 @@ await analytics.identify('some-user-id'); ## Providers -### Google Analytics (Measurement Protocol) +### Google Analytics 4 (Measurement Protocol) Follow [Google's documentation](https://developer.chrome.com/docs/extensions/how-to/integrate/google-analytics-4#setup-credentials) to obtain your credentials: diff --git a/packages/analytics/build.config.ts b/packages/analytics/build.config.ts index e08cc797..850b198d 100644 --- a/packages/analytics/build.config.ts +++ b/packages/analytics/build.config.ts @@ -12,7 +12,7 @@ export default defineBuildConfig({ 'providers/umami.ts', ], replace: { - 'process.env.NPM': 'true', + __PACKAGED__: 'true', }, declaration: true, }); diff --git a/packages/analytics/modules/analytics/client.ts b/packages/analytics/modules/analytics/client.ts index 4d2ceb22..538d05bd 100644 --- a/packages/analytics/modules/analytics/client.ts +++ b/packages/analytics/modules/analytics/client.ts @@ -1,24 +1,15 @@ import { defineWxtPlugin } from 'wxt/sandbox'; import { useAppConfig } from 'wxt/client'; +import { storage } from 'wxt/storage'; import { Analytics, AnalyticsConfig, AnalyticsPageViewEvent, AnalyticsTrackEvent, BaseAnalyticsEvent, - AnalyticsStorageItemConfig, } from './types'; import uaParser from 'ua-parser-js'; -const defineStorageItem = ( - key: string, - defaultValue?: NonNullable, -): AnalyticsStorageItemConfig => ({ - getValue: async () => - (await chrome.storage.local.get(key))[key] ?? defaultValue, - setValue: (newValue) => chrome.storage.local.set({ [key]: newValue }), -}); - export let analytics: Analytics; const ANALYTICS_PORT = 'wxt-analytics'; const interactiveTags = new Set(['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA']); diff --git a/packages/analytics/wxt.config.ts b/packages/analytics/wxt.config.ts index ff3e157b..8b3254ec 100644 --- a/packages/analytics/wxt.config.ts +++ b/packages/analytics/wxt.config.ts @@ -2,7 +2,7 @@ import { defineConfig } from 'wxt'; export default defineConfig({ // Unimport doesn't look for imports in node_modules, so when developing a - // node module, we need to disable this. + // WXT module, we need to disable this to simplify the build process imports: false, manifest: { @@ -10,7 +10,7 @@ export default defineConfig({ }, vite: () => ({ define: { - 'process.env.NPM': 'false', + __PACKAGED__: 'false', }, }), }); diff --git a/packages/auto-icons/README.md b/packages/auto-icons/README.md index 0cef2993..60ee8558 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 @@ -39,4 +41,4 @@ export default defineConfig({ }); ``` -Options have JSDocs available in your editor, or you can read them in the source code: [`AutoIconsOptions`](./src/index.ts). +Options have JSDocs available in your editor, or you can read them in the source code: [`AutoIconsOptions`](https://github.com/wxt-dev/wxt/blob/main/packages/auto-icons/src/index.ts). diff --git a/packages/auto-icons/package.json b/packages/auto-icons/package.json index a2e0584a..5f2e8ff1 100644 --- a/packages/auto-icons/package.json +++ b/packages/auto-icons/package.json @@ -46,9 +46,9 @@ }, "devDependencies": { "@aklinker1/check": "^1.4.5", - "oxlint": "^0.9.1", - "publint": "^0.2.9", - "typescript": "^5.5.4", + "oxlint": "^0.9.9", + "publint": "^0.2.11", + "typescript": "^5.6.2", "unbuild": "^2.0.0", "wxt": "workspace:*" }, diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md new file mode 100644 index 00000000..ec1a39df --- /dev/null +++ b/packages/i18n/CHANGELOG.md @@ -0,0 +1,58 @@ +# Changelog + +## v0.2.1 + +[compare changes](https://github.com/wxt-dev/wxt/compare/i18n-v0.2.0...i18n-v0.2.1) + +### 🩹 Fixes + +- Add missing "type" keyword to type export in generated file ([22b5294](https://github.com/wxt-dev/wxt/commit/22b5294)) + +### πŸ“– Documentation + +- Rewrite and restructure the documentation website ([#933](https://github.com/wxt-dev/wxt/pull/933)) + +### 🏑 Chore + +- Fix typo in internal function name ([21894d2](https://github.com/wxt-dev/wxt/commit/21894d2)) + +### ❀️ Contributors + +- Aaron ([@aklinker1](http://github.com/aklinker1)) + +## v0.2.0 + +[compare changes](https://github.com/wxt-dev/wxt/compare/i18n-v0.1.1...i18n-v0.2.0) + +### 🩹 Fixes + +- ⚠️ Remove invalid options argument ([#1048](https://github.com/wxt-dev/wxt/pull/1048)) + +To upgrade, if you were passing a final `options` argument, remove it. If you used the third argument to escape `<` symbol... You'll need to do it yourself: + +```diff +- i18n.t("someKey", ["sub1"], { escapeLt: true }); ++ i18n.t("someKey", ["sub1"]).replaceAll("<", "<"); +``` + +### ❀️ Contributors + +- Aaron ([@aklinker1](http://github.com/aklinker1)) + +## v0.1.1 + +[compare changes](https://github.com/wxt-dev/wxt/compare/i18n-v0.1.0...i18n-v0.1.1) + +### 🩹 Fixes + +- Friendly error messages for `null` and `undefined` values inside message files ([#1041](https://github.com/wxt-dev/wxt/pull/1041)) + +### 🏑 Chore + +- Add `oxlint` for linting ([#947](https://github.com/wxt-dev/wxt/pull/947)) +- Upgrade all non-major dependencies ([#1040](https://github.com/wxt-dev/wxt/pull/1040)) + +### ❀️ Contributors + +- Windmillcode0 +- Aaron ([@aklinker1](http://github.com/aklinker1)) \ No newline at end of file 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/i18n/package.json b/packages/i18n/package.json index 653b8d54..d079c9e1 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,7 +1,7 @@ { "name": "@wxt-dev/i18n", "description": "Type-safe wrapper around browser.i18n.getMessage with additional features", - "version": "0.1.0", + "version": "0.2.1", "type": "module", "repository": { "type": "git", @@ -40,12 +40,12 @@ "devDependencies": { "@aklinker1/check": "^1.4.5", "@types/chrome": "^0.0.268", - "@types/node": "^20.14.2", - "oxlint": "^0.9.1", - "publint": "^0.2.8", - "typescript": "^5.4.5", + "@types/node": "^20.16.10", + "oxlint": "^0.9.9", + "publint": "^0.2.11", + "typescript": "^5.6.2", "unbuild": "^2.0.0", - "vitest": "^1.6.0", + "vitest": "^2.0.0", "vitest-plugin-random-seed": "^1.1.0", "wxt": "workspace:*" }, diff --git a/packages/i18n/src/__tests__/build.test.ts b/packages/i18n/src/__tests__/build.test.ts index 7e77b551..ef05be0c 100644 --- a/packages/i18n/src/__tests__/build.test.ts +++ b/packages/i18n/src/__tests__/build.test.ts @@ -161,4 +161,17 @@ describe('Built Tools', () => { ); expect(mockWriteFile).toBeCalledWith('output.d.ts', expectedDts, 'utf8'); }); + + it('should throw an error if messages file contains null or undefined', async () => { + const invalidFileContent = stringifyYAML({ + simple: 'example', + invalidField: null, + }); + + mockReadFile.mockResolvedValue(invalidFileContent); + + await expect(parseMessagesFile('invalid.yml')).rejects.toThrowError( + 'Messages file should not contain `null` (found at "invalidField")', + ); + }); }); diff --git a/packages/i18n/src/__tests__/index.test.ts b/packages/i18n/src/__tests__/index.test.ts index 8ac650fd..2ffc37f6 100644 --- a/packages/i18n/src/__tests__/index.test.ts +++ b/packages/i18n/src/__tests__/index.test.ts @@ -1,6 +1,5 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { createI18n } from '../index'; -import { GetMessageOptions } from '../types'; const getMessageMock = vi.fn(); @@ -28,7 +27,7 @@ describe('createI18n', () => { expect(actual).toBe(expectedValue); expect(getMessageMock).toBeCalledTimes(1); - expect(getMessageMock).toBeCalledWith(expectedKey, undefined); + expect(getMessageMock).toBeCalledWith(expectedKey); }); it.each([ @@ -55,28 +54,13 @@ describe('createI18n', () => { expect(actual).toBe(expected); expect(getMessageMock).toBeCalledTimes(1); - expect(getMessageMock).toBeCalledWith(key, [String(count)], undefined); + expect(getMessageMock).toBeCalledWith(key, [String(count)]); }, ); it('should allow overriding the plural substitutions', () => { const i18n = createI18n(); i18n.t('key', 3, ['custom']); - expect(getMessageMock).toBeCalledWith('key', ['custom'], undefined); - }); - - it('should pass options into browser.i18n.getMessage', () => { - const i18n = createI18n(); - const options: GetMessageOptions = { - escapeLt: true, - }; - - i18n.t('key', options); - i18n.t('key', [''], options); - i18n.t('key', 1, options); - i18n.t('key', 1, [''], options); - getMessageMock.mock.calls.forEach((call) => { - expect(call.pop()).toEqual(options); - }); + expect(getMessageMock).toBeCalledWith('key', ['custom']); }); }); diff --git a/packages/i18n/src/__tests__/types.test.ts b/packages/i18n/src/__tests__/types.test.ts index be40b094..6c7999bc 100644 --- a/packages/i18n/src/__tests__/types.test.ts +++ b/packages/i18n/src/__tests__/types.test.ts @@ -22,13 +22,9 @@ describe('I18n Types', () => { describe('t', () => { it('should allow passing any combination of arguments', () => { i18n.t('any'); - i18n.t('any', { escapeLt: true }); i18n.t('any', ['one']); - i18n.t('any', ['one'], { escapeLt: true }); i18n.t('any', ['one', 'two']); - i18n.t('any', ['one', 'two'], { escapeLt: true }); i18n.t('any', n, ['one', 'two']); - i18n.t('any', n, ['one', 'two'], { escapeLt: true }); }); }); }); @@ -46,7 +42,6 @@ describe('I18n Types', () => { describe('t', () => { it('should only allow passing valid combinations of arguments', () => { i18n.t('simple'); - i18n.t('simple', { escapeLt: true }); // @ts-expect-error i18n.t('simple', []); // @ts-expect-error @@ -55,7 +50,6 @@ describe('I18n Types', () => { i18n.t('simple', n); i18n.t('simpleSub1', ['one']); - i18n.t('simpleSub1', ['one'], { escapeLt: true }); // @ts-expect-error i18n.t('simpleSub1'); // @ts-expect-error @@ -66,7 +60,6 @@ describe('I18n Types', () => { i18n.t('simpleSub1', n); i18n.t('simpleSub2', ['one', 'two']); - i18n.t('simpleSub2', ['one', 'two'], { escapeLt: true }); // @ts-expect-error i18n.t('simpleSub2'); // @ts-expect-error @@ -77,7 +70,6 @@ describe('I18n Types', () => { i18n.t('simpleSub2', n); i18n.t('plural', n); - i18n.t('plural', n, { escapeLt: true }); // @ts-expect-error i18n.t('plural'); // @ts-expect-error @@ -88,10 +80,8 @@ describe('I18n Types', () => { i18n.t('plural', n, ['sub']); i18n.t('pluralSub1', n); - i18n.t('pluralSub1', n, { escapeLt: true }); - i18n.t('pluralSub1', n, undefined, { escapeLt: true }); + i18n.t('pluralSub1', n, undefined); i18n.t('pluralSub1', n, ['one']); - i18n.t('pluralSub1', n, ['one'], { escapeLt: true }); // @ts-expect-error i18n.t('pluralSub1'); // @ts-expect-error @@ -102,7 +92,6 @@ describe('I18n Types', () => { i18n.t('pluralSub1', n, ['one', 'two']); i18n.t('pluralSub2', n, ['one', 'two']); - i18n.t('pluralSub2', n, ['one', 'two'], { escapeLt: true }); // @ts-expect-error i18n.t('pluralSub2'); // @ts-expect-error diff --git a/packages/i18n/src/__tests__/utils.test.ts b/packages/i18n/src/__tests__/utils.test.ts index 21477224..e3ef657e 100644 --- a/packages/i18n/src/__tests__/utils.test.ts +++ b/packages/i18n/src/__tests__/utils.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect } from 'vitest'; import { ChromeMessage } from '../build'; -import { applyChromeMessagePlaceholders, getSubstitionCount } from '../utils'; +import { applyChromeMessagePlaceholders, getSubstitutionCount } from '../utils'; describe('Utils', () => { describe('applyChromeMessagePlaceholders', () => { @@ -38,26 +38,26 @@ describe('Utils', () => { }); }); - describe('getSubstitionCount', () => { + describe('getSubstitutionCount', () => { it('should return the last substution present in the message', () => { - expect(getSubstitionCount('I like $1, but I like $2 better')).toBe(2); + expect(getSubstitutionCount('I like $1, but I like $2 better')).toBe(2); }); it('should return 0 when no substitutions are present', () => { - expect(getSubstitionCount('test')).toBe(0); + expect(getSubstitutionCount('test')).toBe(0); }); it('should ignore escaped dollar signs', () => { - expect(getSubstitionCount('buy $1 now for $$2 dollars')).toBe(1); + expect(getSubstitutionCount('buy $1 now for $$2 dollars')).toBe(1); }); it('should return the highest substitution when skipping numbers', () => { - expect(getSubstitionCount('I like $1, but I like $8 better')).toBe(8); + expect(getSubstitutionCount('I like $1, but I like $8 better')).toBe(8); }); it('should only allow up to 9 substitutions', () => { - expect(getSubstitionCount('Hello $9')).toBe(9); - expect(getSubstitionCount('Hello $10')).toBe(1); + expect(getSubstitutionCount('Hello $9')).toBe(9); + expect(getSubstitutionCount('Hello $10')).toBe(1); }); }); }); diff --git a/packages/i18n/src/build.ts b/packages/i18n/src/build.ts index 8d861a67..7ad7aef8 100644 --- a/packages/i18n/src/build.ts +++ b/packages/i18n/src/build.ts @@ -8,7 +8,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises'; import { parseYAML, parseJSON5, parseTOML } from 'confbox'; import { dirname, extname } from 'node:path'; -import { applyChromeMessagePlaceholders, getSubstitionCount } from './utils'; +import { applyChromeMessagePlaceholders, getSubstitutionCount } from './utils'; // // TYPES @@ -155,7 +155,7 @@ function _parseMessagesObject( case 'number': case 'symbol': { const message = String(object); - const substitutions = getSubstitionCount(message); + const substitutions = getSubstitutionCount(message); return [ { type: 'simple', @@ -166,13 +166,18 @@ function _parseMessagesObject( ]; } case 'object': + if ([null, undefined].includes(object)) { + throw new Error( + `Messages file should not contain \`${object}\` (found at "${path.join('.')}")`, + ); + } if (Array.isArray(object)) return object.flatMap((item, i) => _parseMessagesObject(path.concat(String(i)), item, depth + 1), ); if (isPluralMessage(object)) { const message = Object.values(object).join('|'); - const substitutions = getSubstitionCount(message); + const substitutions = getSubstitutionCount(message); return [ { type: 'plural', @@ -184,7 +189,7 @@ function _parseMessagesObject( } if (depth === 1 && isChromeMessage(object)) { const message = applyChromeMessagePlaceholders(object); - const substitutions = getSubstitionCount(message); + const substitutions = getSubstitutionCount(message); return [ { type: 'chrome', diff --git a/packages/i18n/src/index.ts b/packages/i18n/src/index.ts index 2975efae..b5b01b9a 100644 --- a/packages/i18n/src/index.ts +++ b/packages/i18n/src/index.ts @@ -6,7 +6,6 @@ import { DefaultI18nStructure, I18n, Substitution, - GetMessageOptions, } from './types'; export function createI18n< @@ -16,7 +15,6 @@ export function createI18n< // Resolve args let sub: Substitution[] | undefined; let count: number | undefined; - let options: GetMessageOptions | undefined; args.forEach((arg, i) => { if (arg == null) { // ignore nullish args @@ -24,8 +22,6 @@ export function createI18n< count = arg; } else if (Array.isArray(arg)) { sub = arg; - } else if (typeof arg === 'object') { - options = arg; } else { throw Error( `Unknown argument at index ${i}. Must be a number for pluralization, substitution array, or options object.`, @@ -43,18 +39,9 @@ export function createI18n< if (sub?.length) { // Convert all substitutions to strings const stringSubs = sub?.map((sub) => String(sub)); - message = chrome.i18n.getMessage( - key.replaceAll('.', '_'), - stringSubs, - // @ts-ignore - @types/chrome doesn't type the options object, but it's there - options, - ); + message = chrome.i18n.getMessage(key.replaceAll('.', '_'), stringSubs); } else { - message = chrome.i18n.getMessage( - key.replaceAll('.', '_'), - // @ts-ignore - @types/chrome doesn't type the options object, but it's there - options, - ); + message = chrome.i18n.getMessage(key.replaceAll('.', '_')); } if (!message) { console.warn(`[i18n] Message not found: "${key}"`); diff --git a/packages/i18n/src/module.ts b/packages/i18n/src/module.ts index bd7bb368..2699f503 100644 --- a/packages/i18n/src/module.ts +++ b/packages/i18n/src/module.ts @@ -128,7 +128,7 @@ import type { GeneratedI18nStructure } from './structure'; export const i18n = createI18n(); -export { GeneratedI18nStructure } +export { type GeneratedI18nStructure } `, }); }); diff --git a/packages/i18n/src/types.ts b/packages/i18n/src/types.ts index 28b9677b..d742c873 100644 --- a/packages/i18n/src/types.ts +++ b/packages/i18n/src/types.ts @@ -29,7 +29,6 @@ export type TFunction = { ( // prettier-ignore key: K & { [P in keyof T]: T[P] extends { plural: false; substitutions: 0 } ? P : never; }[keyof T], - options?: GetMessageOptions, ): string; // Non-plural with substitutions @@ -39,7 +38,6 @@ export type TFunction = { substitutions: T[K] extends I18nFeatures ? SubstitutionTuple : never, - options?: GetMessageOptions, ): string; // Plural with 1 substitution @@ -48,7 +46,6 @@ export type TFunction = { key: K & { [P in keyof T]: T[P] extends { plural: true; substitutions: 1 } ? P : never; }[keyof T], n: number, substitutions?: SubstitutionTuple<1>, - options?: GetMessageOptions, ): string; // Plural without substitutions @@ -56,7 +53,6 @@ export type TFunction = { // prettier-ignore key: K & { [P in keyof T]: T[P] extends { plural: true; substitutions: 0 | 1 } ? P : never; }[keyof T], n: number, - options?: GetMessageOptions, ): string; // Plural with substitutions @@ -67,7 +63,6 @@ export type TFunction = { substitutions: T[K] extends I18nFeatures ? SubstitutionTuple : never, - options?: GetMessageOptions, ): string; }; @@ -77,13 +72,4 @@ export interface I18n { export type Substitution = string | number; -export interface GetMessageOptions { - /** - * Escape `<` in translation to `<`. This applies only to the message itself, not to the placeholders. Developers might want to use this if the translation is used in an HTML context. Closure Templates used with Closure Compiler generate this automatically. - * - * See https://developer.chrome.com/docs/extensions/reference/api/i18n#type-getMessage-options - */ - escapeLt?: boolean; -} - type SubstitutionCount = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; diff --git a/packages/i18n/src/utils.ts b/packages/i18n/src/utils.ts index 905aa1c0..cb9b9634 100644 --- a/packages/i18n/src/utils.ts +++ b/packages/i18n/src/utils.ts @@ -11,7 +11,7 @@ export function applyChromeMessagePlaceholders(message: ChromeMessage): string { ); } -export function getSubstitionCount(message: string): number { +export function getSubstitutionCount(message: string): number { return ( 1 + Array.from({ length: MAX_SUBSTITUTIONS }).findLastIndex((_, i) => diff --git a/packages/module-react/package.json b/packages/module-react/package.json index 029f20c0..cae6ef57 100644 --- a/packages/module-react/package.json +++ b/packages/module-react/package.json @@ -47,16 +47,16 @@ "wxt": ">=0.18.6" }, "dependencies": { - "@vitejs/plugin-react": "^4.3.1" + "@vitejs/plugin-react": "^4.3.2" }, "devDependencies": { "@aklinker1/check": "^1.4.5", - "@types/react": "^18.3.3", + "@types/react": "^18.3.11", "@types/react-dom": "^18.3.0", - "publint": "^0.2.9", + "publint": "^0.2.11", "react": "^18.3.1", "react-dom": "^18.3.1", - "typescript": "^5.5.4", + "typescript": "^5.6.2", "unbuild": "^2.0.0", "wxt": "workspace:*" } diff --git a/packages/module-solid/package.json b/packages/module-solid/package.json index 4e02a4d2..81fcb53c 100644 --- a/packages/module-solid/package.json +++ b/packages/module-solid/package.json @@ -51,9 +51,9 @@ }, "devDependencies": { "@aklinker1/check": "^1.4.5", - "publint": "^0.2.9", - "solid-js": "^1.8.19", - "typescript": "^5.5.4", + "publint": "^0.2.11", + "solid-js": "^1.9.1", + "typescript": "^5.6.2", "unbuild": "^2.0.0", "wxt": "workspace:*" } diff --git a/packages/module-svelte/package.json b/packages/module-svelte/package.json index 5cc7157a..61a6d1d6 100644 --- a/packages/module-svelte/package.json +++ b/packages/module-svelte/package.json @@ -45,12 +45,12 @@ "wxt": ">=0.18.6" }, "dependencies": { - "@sveltejs/vite-plugin-svelte": "^3.1.1" + "@sveltejs/vite-plugin-svelte": "^3.1.2" }, "devDependencies": { "@aklinker1/check": "^1.4.5", - "publint": "^0.2.9", - "typescript": "^5.5.4", + "publint": "^0.2.11", + "typescript": "^5.6.2", "unbuild": "^2.0.0", "wxt": "workspace:*" } diff --git a/packages/module-vue/package.json b/packages/module-vue/package.json index 6f8bd373..a0e77d38 100644 --- a/packages/module-vue/package.json +++ b/packages/module-vue/package.json @@ -45,12 +45,12 @@ "wxt": ">=0.18.6" }, "dependencies": { - "@vitejs/plugin-vue": "^5.1.1" + "@vitejs/plugin-vue": "^5.1.4" }, "devDependencies": { "@aklinker1/check": "^1.4.5", - "publint": "^0.2.9", - "typescript": "^5.5.4", + "publint": "^0.2.11", + "typescript": "^5.6.2", "unbuild": "^2.0.0", "wxt": "workspace:*" } diff --git a/packages/unocss/README.md b/packages/unocss/README.md new file mode 100644 index 00000000..b3476738 --- /dev/null +++ b/packages/unocss/README.md @@ -0,0 +1,47 @@ +# WXT UnoCSS + +Use UnoCSS in your WXT extension! + +## Usage + +Install the package: + +```sh +npm i --save-dev @wxt-dev/unocss unocss +pnpm i -D @wxt-dev/unocss unocss +yarn add --dev @wxt-dev/unocss unocss +bun i -D @wxt-dev/unocss unocss +``` + +Add the module to `wxt.config.ts`: + +```ts +export default defineConfig({ + modules: ['@wxt-dev/unocss'], +}); +``` + +Now in your entrypoint, import UnoCSS: + +```ts +import 'uno.css'; +``` + +> [!IMPORTANT] +> While in dev mode, you may see a warning about `uno.css` not being found. This is because in development, we don't know which files should be injected with UnoCSS styles. The warning can be safely ignored as the styles will be properly applied during the build process. + +## Configuration + +The module can be configured via the `unocss` config: + +```ts +export default defineConfig({ + modules: ['@wxt-dev/unocss'], + unocss: { + // Will only apply unocss for popup/main.ts + entrypoints: ['popup/main.ts'], + }, +}); +``` + +Options have JSDocs available in your editor, or you can read them in the source code: [`UnoCSSOptions`](https://github.com/wxt-dev/wxt/blob/main/packages/auto-icons/src/index.ts). diff --git a/packages/unocss/package.json b/packages/unocss/package.json new file mode 100644 index 00000000..c50ab9d4 --- /dev/null +++ b/packages/unocss/package.json @@ -0,0 +1,55 @@ +{ + "name": "@wxt-dev/unocss", + "description": "UnoCSS integration for WXT", + "version": "1.0.0", + "repository": { + "type": "git", + "url": "git+https://github.com/wxt-dev/wxt.git", + "directory": "packages/unocss" + }, + "homepage": "http://wxt.dev/guide/unocss.html", + "keywords": [ + "wxt", + "module", + "unocss", + "css" + ], + "author": { + "name": "Florian Metz", + "email": "me@timeraa.dev" + }, + "license": "MIT", + "type": "module", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "buildc -- unbuild", + "check": "buildc --deps-only -- check" + }, + "peerDependencies": { + "unocss": ">=0.60.0", + "wxt": ">=0.19.0" + }, + "devDependencies": { + "@aklinker1/check": "^1.4.5", + "oxlint": "^0.9.9", + "publint": "^0.2.11", + "typescript": "^5.6.2", + "unbuild": "^2.0.0", + "unocss": "^0.63.3", + "wxt": "workspace:*" + }, + "dependencies": { + "defu": "^6.1.4", + "fast-glob": "^3.3.2" + } +} diff --git a/packages/unocss/src/index.ts b/packages/unocss/src/index.ts new file mode 100644 index 00000000..18ebf51c --- /dev/null +++ b/packages/unocss/src/index.ts @@ -0,0 +1,68 @@ +import 'wxt'; +import { defineWxtModule } from 'wxt/modules'; +import defu from 'defu'; +import UnoCSS from 'unocss/vite'; + +export default defineWxtModule({ + name: '@wxt-dev/unocss', + configKey: 'unocss', + async setup(wxt, options) { + const resolvedOptions = defu, UnoCSSOptions[]>( + options, + { + enabled: true, + excludeEntrypoints: ['background'], + configOrPath: undefined, + }, + ); + + if (!resolvedOptions.enabled) + return wxt.logger.warn(`\`[unocss]\` ${this.name} disabled`); + + const excludedEntrypoints = new Set(resolvedOptions.excludeEntrypoints); + if (wxt.config.debug) { + wxt.logger.debug( + `\`[unocss]\` Excluded entrypoints:`, + [...excludedEntrypoints].join(', '), + ); + } + + wxt.hooks.hook('vite:devServer:extendConfig', (config) => { + config.plugins?.push(UnoCSS()); + }); + + wxt.hooks.hook('vite:build:extendConfig', async (entries, config) => { + if (entries.every((entry) => excludedEntrypoints.has(entry.name))) return; + config.plugins?.push(UnoCSS(resolvedOptions.configOrPath)); + }); + }, +}); + +/** + * Options for the UnoCSS module + */ +export interface UnoCSSOptions { + /** + * Enable UnoCSS + * @default true + */ + enabled?: boolean; + /** + * List of entrypoint names that UnoCSS is not used in. By default, the UnoCSS + * vite plugin is added to all build steps, but this option is used to exclude + * it from specific builds. + * @example ["popup", "options"] + * @default [] + */ + excludeEntrypoints?: string[]; + /** + * The path to your `unocss.config.ts` file, relative to , or inline configuration. + */ + configOrPath?: Parameters>[0]; +} + +declare module 'wxt' { + export interface InlineConfig { + unocss?: UnoCSSOptions; + } +} diff --git a/packages/unocss/tsconfig.json b/packages/unocss/tsconfig.json new file mode 100644 index 00000000..9b2dc061 --- /dev/null +++ b/packages/unocss/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.base.json", + "exclude": ["node_modules/**", "dist/**"] +} diff --git a/packages/wxt-demo/package.json b/packages/wxt-demo/package.json index 53e1d202..5ea0a281 100644 --- a/packages/wxt-demo/package.json +++ b/packages/wxt-demo/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "buildc --deps-only -- wxt", "build": "buildc --deps-only -- wxt build", - "build:all": "buildc --deps-only -- run-s -s 'build:all:*'", + "build:all": "buildc --deps-only -- pnpm run --reporter-hide-prefix /^build:all:.*/", "build:all:chrome-mv3": "wxt build", "build:all:chrome-mv2": "wxt build --mv2", "build:all:firefox-mv3": "wxt build -b firefox --mv3", @@ -23,12 +23,14 @@ }, "devDependencies": { "@types/chrome": "^0.0.269", - "@types/react": "^18.3.3", + "@types/react": "^18.3.11", "@types/react-dom": "^18.3.0", "@wxt-dev/auto-icons": "workspace:*", - "sass": "^1.77.8", - "typescript": "^5.5.4", - "vitest": "^2.0.4", + "@wxt-dev/unocss": "workspace:*", + "sass": "^1.79.4", + "typescript": "^5.6.2", + "unocss": "^0.63.3", + "vitest": "^2.1.2", "vitest-plugin-random-seed": "^1.1.0", "wxt": "workspace:*" }, diff --git a/packages/wxt-demo/src/common/style.css b/packages/wxt-demo/src/common/style.css deleted file mode 100644 index ea1e941c..00000000 --- a/packages/wxt-demo/src/common/style.css +++ /dev/null @@ -1,4 +0,0 @@ -body { - margin: 0; - padding: 0; -} diff --git a/packages/wxt-demo/src/entrypoints/popup.html b/packages/wxt-demo/src/entrypoints/popup.html index 624c1bce..c8f20f68 100644 --- a/packages/wxt-demo/src/entrypoints/popup.html +++ b/packages/wxt-demo/src/entrypoints/popup.html @@ -4,7 +4,7 @@ Popup - +

Hello popup!

diff --git a/packages/wxt-demo/src/entrypoints/ui.content/index.ts b/packages/wxt-demo/src/entrypoints/ui.content/index.ts index f552d8e6..914e73c3 100644 --- a/packages/wxt-demo/src/entrypoints/ui.content/index.ts +++ b/packages/wxt-demo/src/entrypoints/ui.content/index.ts @@ -1,4 +1,4 @@ -import '../../common/style.css'; +import 'uno.css'; import './style.css'; export default defineContentScript({ @@ -13,6 +13,7 @@ export default defineContentScript({ anchor: 'form[role=search]', onMount: (container) => { const app = document.createElement('div'); + app.classList.add('m-4', 'text-red-500'); app.textContent = i18n.t('prompt_for_name'); container.append(app); }, diff --git a/packages/wxt-demo/src/entrypoints/ui.content/style.css b/packages/wxt-demo/src/entrypoints/ui.content/style.css index ce526c21..3bfc8130 100644 --- a/packages/wxt-demo/src/entrypoints/ui.content/style.css +++ b/packages/wxt-demo/src/entrypoints/ui.content/style.css @@ -1,11 +1,6 @@ :root { color-scheme: dark; - color: indianred; } html { background-color: black; } - -div { - padding: 16px; -} diff --git a/packages/wxt-demo/src/modules/unocss.ts b/packages/wxt-demo/src/modules/unocss.ts new file mode 100644 index 00000000..f184c4d5 --- /dev/null +++ b/packages/wxt-demo/src/modules/unocss.ts @@ -0,0 +1 @@ +export { default } from '@wxt-dev/unocss'; diff --git a/packages/wxt-demo/wxt.config.ts b/packages/wxt-demo/wxt.config.ts index 57f8d520..f732c1c3 100644 --- a/packages/wxt-demo/wxt.config.ts +++ b/packages/wxt-demo/wxt.config.ts @@ -1,4 +1,5 @@ import { defineConfig } from 'wxt'; +import { presetUno } from 'unocss'; export default defineConfig({ srcDir: 'src', @@ -27,4 +28,32 @@ export default defineConfig({ // @ts-expect-error: c is not defined, this should error out c: 'c', }, + unocss: { + excludeEntrypoints: [ + 'example', + 'iframe-src', + 'injected', + 'example-tsx', + 'example-2', + 'iframe', + 'location-change', + 'main-world', + 'sandbox', + 'sidepanel', + 'unlisted', + ], + configOrPath: { + content: { + pipeline: { + include: [ + // the default + /\.(vue|svelte|[jt]sx|mdx?|astro|elm|php|phtml|html)($|\?)/, + // include js/ts files + 'src/entrypoints/**/*.{js,ts}', + ], + }, + }, + presets: [presetUno()], + }, + }, }); diff --git a/packages/wxt/CHANGELOG.md b/packages/wxt/CHANGELOG.md index 586810b4..b1be4b69 100644 --- a/packages/wxt/CHANGELOG.md +++ b/packages/wxt/CHANGELOG.md @@ -1,5 +1,115 @@ # Changelog +## v0.19.13 + +[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.12...wxt-v0.19.13) + +### πŸš€ Enhancements + +- **env:** Load env from `.env.[browser]` variants ([#1078](https://github.com/wxt-dev/wxt/pull/1078)) + +### 🩹 Fixes + +- Don't use `#private` member variables in `ContentScriptContext` ([#1103](https://github.com/wxt-dev/wxt/pull/1103)) + +### ❀️ Contributors + +- Aaron ([@aklinker1](http://github.com/aklinker1)) +- Craig Slusher ([@sleekslush](http://github.com/sleekslush)) + +## v0.19.12 + +[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.11...wxt-v0.19.12) + +### πŸš€ Enhancements + +- Add support for `WXT_` environment variable prefix ([#1076](https://github.com/wxt-dev/wxt/pull/1076)) +- **config:** Add `outDirTemplate` for customizing output directory structure ([#1074](https://github.com/wxt-dev/wxt/pull/1074)) + +### πŸ”₯ Performance + +- Replace `execa` with `nano-spawn` for smaller package size ([#1042](https://github.com/wxt-dev/wxt/pull/1042)) +- Downgrade `esbuild` so a single version is shared between sub-dependencies ([#1045](https://github.com/wxt-dev/wxt/pull/1045)) + +### 🩹 Fixes + +- Use directory name when `zip.name` and `package.json#name` are not provided ([#1028](https://github.com/wxt-dev/wxt/pull/1028)) +- Ensure consistent hook execution order and add docs ([#1081](https://github.com/wxt-dev/wxt/pull/1081)) + +### πŸ“– Documentation + +- Rewrite and restructure the documentation website ([#933](https://github.com/wxt-dev/wxt/pull/933)) + +### 🏑 Chore + +- Remove email from changelog ([#1027](https://github.com/wxt-dev/wxt/pull/1027)) +- **deps:** Bump magicast from 0.3.4 to 0.3.5 ([#1017](https://github.com/wxt-dev/wxt/pull/1017)) +- **deps:** Bump esbuild from 0.23.0 to 0.24.0 ([#1018](https://github.com/wxt-dev/wxt/pull/1018)) +- **deps:** Bump linkedom from 0.18.4 to 0.18.5 ([#1034](https://github.com/wxt-dev/wxt/pull/1034)) +- **deps:** Bump execa from 9.3.1 to 9.4.0 ([#1031](https://github.com/wxt-dev/wxt/pull/1031)) +- Upgrade all non-major dependencies ([#1040](https://github.com/wxt-dev/wxt/pull/1040)) +- Shrink down on dependencies ([#1050](https://github.com/wxt-dev/wxt/pull/1050)) +- Enable `extensionApi: chrome` in template projects ([#1083](https://github.com/wxt-dev/wxt/pull/1083)) + +### ❀️ Contributors + +- Aaron ([@aklinker1](http://github.com/aklinker1)) +- Florian Metz ([@Timeraa](http://github.com/Timeraa)) +- Mezannic ([@mezannic](http://github.com/mezannic)) + +## v0.19.11 + +[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.10...wxt-v0.19.11) + +### πŸš€ Enhancements + +- **zip:** Hooks ([#993](https://github.com/wxt-dev/wxt/pull/993)) +- **zip:** `wxt zip --sources` and auto sources for opera ([#1014](https://github.com/wxt-dev/wxt/pull/1014)) + +### 🩹 Fixes + +- Reverse env files priority ([#1016](https://github.com/wxt-dev/wxt/pull/1016)) +- #1005 fixed, by updating type-definations to getItem method. ([#1007](https://github.com/wxt-dev/wxt/pull/1007), [#1005](https://github.com/wxt-dev/wxt/issues/1005)) + +### 🏑 Chore + +- Move some files around ([#996](https://github.com/wxt-dev/wxt/pull/996)) + +### ❀️ Contributors + +- Florian Metz ([@Timeraa](http://github.com/Timeraa)) +- Gurvir Singh ([@baraich](http://github.com/baraich)) +- Mezannic ([@mezannic](http://github.com/mezannic)) +- Aaron ([@aklinker1](http://github.com/aklinker1)) + +## v0.19.10 + +[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.9...wxt-v0.19.10) + +### πŸ”₯ Performance + +- Reduce hypersensitive onChange of watcher ([#978](https://github.com/wxt-dev/wxt/pull/978)) + +### 🩹 Fixes + +- Fix config manifest type ([#973](https://github.com/wxt-dev/wxt/pull/973)) + +### πŸ“– Documentation + +- Examples reference outDir vs. outputDir ([#982](https://github.com/wxt-dev/wxt/pull/982)) +- Improved docs and links ([#970](https://github.com/wxt-dev/wxt/pull/970)) + +### 🌊 Types + +- Fix `ExtensionRunnerConfig.chromiumPref` type ([fda1e18](https://github.com/wxt-dev/wxt/commit/fda1e18)) + +### ❀️ Contributors + +- 1natsu ([@1natsu172](http://github.com/1natsu172)) +- Okinea Dev ([@okineadev](http://github.com/okineadev)) +- The-syndrome +- Hikiko4ern ([@hikiko4ern](http://github.com/hikiko4ern)) + ## v0.19.9 [compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.8...wxt-v0.19.9) @@ -2468,4 +2578,4 @@ Initial release of WXT. Full support for production builds and initial toolkit f ### πŸ€– CI - Create validation workflow ([#12](https://github.com/wxt-dev/wxt/pull/12)) -- Create release workflow ([#13](https://github.com/wxt-dev/wxt/pull/13)) \ No newline at end of file +- Create release workflow ([#13](https://github.com/wxt-dev/wxt/pull/13)) diff --git a/packages/wxt/README.md b/packages/wxt/README.md index a34a8f8e..530b187b 100644 --- a/packages/wxt/README.md +++ b/packages/wxt/README.md @@ -1,16 +1,17 @@ +

- WXT Logo + WXT Logo WXT

- npm + npm version - npm + downloads - NPM + license | MIT - Codecov + coverage

@@ -18,7 +19,7 @@
⚑
- It's like Nuxt, but for Chrome Extensions + It's like Nuxt, but for Web Extensions

@@ -43,10 +44,21 @@ https://github.com/wxt-dev/wxt/assets/10101283/4d678939-1bdb-495c-9c36-3aa281d84 Bootstrap a new project: + + ```sh -pnpm dlx wxt@latest init +# npm +npx wxt@latest init + +# pnpm +pnpm dlx wxt@latest init + +# bun +bunx wxt@latest init ``` + + Or see the [installation guide](https://wxt.dev/guide/installation.html) to get started with WXT. ## Features @@ -59,13 +71,20 @@ 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 ## Contributors + + +Published under the [MIT](https://github.com/wxt-dev/wxt/blob/main/LICENSE) license. +Made by [@aklinker1](https://github.com/aklinker1) and [community](https://github.com/wxt-dev/wxt/graphs/contributors) πŸ’› +

- + + + diff --git a/packages/wxt/e2e/tests/auto-imports.test.ts b/packages/wxt/e2e/tests/auto-imports.test.ts index c1eecb5f..167b33a4 100644 --- a/packages/wxt/e2e/tests/auto-imports.test.ts +++ b/packages/wxt/e2e/tests/auto-imports.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect } from 'vitest'; import { TestProject } from '../utils'; -import { execaCommand } from 'execa'; +import spawn from 'nano-spawn'; describe('Auto Imports', () => { describe('imports: { ... }', () => { @@ -180,7 +180,7 @@ describe('Auto Imports', () => { await project.prepare({ imports: { eslintrc: { enabled: version } }, }); - return await execaCommand('pnpm eslint entrypoints/background.js', { + return await spawn('pnpm', ['eslint', 'entrypoints/background.js'], { cwd: project.root, }); } @@ -205,7 +205,8 @@ describe('Auto Imports', () => { ); await expect(runEslint(project, 9)).rejects.toMatchObject({ - message: expect.stringContaining( + exitCode: 1, + stdout: expect.stringContaining( "'defineBackground' is not defined", ), }); @@ -253,7 +254,8 @@ describe('Auto Imports', () => { ); await expect(runEslint(project, 8)).rejects.toMatchObject({ - message: expect.stringContaining( + exitCode: 1, + stdout: expect.stringContaining( "'defineBackground' is not defined", ), }); diff --git a/packages/wxt/e2e/tests/hooks.test.ts b/packages/wxt/e2e/tests/hooks.test.ts index a00b986a..e91a2209 100644 --- a/packages/wxt/e2e/tests/hooks.test.ts +++ b/packages/wxt/e2e/tests/hooks.test.ts @@ -14,6 +14,12 @@ const hooks: WxtHooks = { 'entrypoints:grouped': vi.fn(), 'vite:build:extendConfig': vi.fn(), 'vite:devServer:extendConfig': vi.fn(), + 'zip:start': vi.fn(), + 'zip:extension:start': vi.fn(), + 'zip:extension:done': vi.fn(), + 'zip:sources:start': vi.fn(), + 'zip:sources:done': vi.fn(), + 'zip:done': vi.fn(), }; function expectHooksToBeCalled( @@ -53,6 +59,12 @@ describe('Hooks', () => { 'entrypoints:resolved': true, 'vite:build:extendConfig': false, 'vite:devServer:extendConfig': false, + 'zip:start': false, + 'zip:extension:start': false, + 'zip:extension:done': false, + 'zip:sources:start': false, + 'zip:sources:done': false, + 'zip:done': false, }); }); @@ -74,6 +86,12 @@ describe('Hooks', () => { 'entrypoints:resolved': true, 'vite:build:extendConfig': 1, 'vite:devServer:extendConfig': false, + 'zip:start': false, + 'zip:extension:start': false, + 'zip:extension:done': false, + 'zip:sources:start': false, + 'zip:sources:done': false, + 'zip:done': false, }); }); @@ -95,6 +113,39 @@ describe('Hooks', () => { 'entrypoints:resolved': true, 'vite:build:extendConfig': 1, 'vite:devServer:extendConfig': false, + 'zip:start': true, + 'zip:extension:start': true, + 'zip:extension:done': true, + 'zip:sources:start': false, + 'zip:sources:done': false, + 'zip:done': true, + }); + }); + + it('zip -b firefox should call hooks', async () => { + const project = new TestProject(); + project.addFile('entrypoints/popup.html', ''); + + await project.zip({ hooks, browser: 'firefox' }); + + expectHooksToBeCalled({ + ready: true, + 'prepare:types': true, + 'prepare:publicPaths': true, + 'build:before': true, + 'build:done': true, + 'build:publicAssets': true, + 'build:manifestGenerated': true, + 'entrypoints:grouped': true, + 'entrypoints:resolved': true, + 'vite:build:extendConfig': 1, + 'vite:devServer:extendConfig': false, + 'zip:start': true, + 'zip:extension:start': true, + 'zip:extension:done': true, + 'zip:sources:start': true, + 'zip:sources:done': true, + 'zip:done': true, }); }); @@ -122,6 +173,12 @@ describe('Hooks', () => { 'entrypoints:resolved': true, 'vite:build:extendConfig': 2, 'vite:devServer:extendConfig': 1, + 'zip:start': false, + 'zip:extension:start': false, + 'zip:extension:done': false, + 'zip:sources:start': false, + 'zip:sources:done': false, + 'zip:done': false, }); }); }); diff --git a/packages/wxt/e2e/tests/init.test.ts b/packages/wxt/e2e/tests/init.test.ts index 269a86ce..a004be04 100644 --- a/packages/wxt/e2e/tests/init.test.ts +++ b/packages/wxt/e2e/tests/init.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect } from 'vitest'; import { TestProject, WXT_PACKAGE_DIR } from '../utils'; -import { execaCommand } from 'execa'; +import spawn from 'nano-spawn'; import glob from 'fast-glob'; import { mkdir, writeJson } from 'fs-extra'; @@ -8,11 +8,15 @@ describe('Init command', () => { it('should download and create a template', async () => { const project = new TestProject(); - await execaCommand(`pnpm -s wxt init ${project.root} -t vue --pm npm`, { - env: { ...process.env, CI: 'true' }, - stdio: 'ignore', - cwd: WXT_PACKAGE_DIR, - }); + await spawn( + 'pnpm', + ['-s', 'wxt', 'init', project.root, '-t', 'vue', '--pm', 'npm'], + { + env: { CI: 'true' }, + stdio: 'ignore', + cwd: WXT_PACKAGE_DIR, + }, + ); const files = await glob('**/*', { cwd: project.root, onlyFiles: true, @@ -51,11 +55,15 @@ describe('Init command', () => { await writeJson(project.resolvePath('package.json'), {}); await expect(() => - execaCommand(`pnpm -s wxt init ${project.root} -t vue --pm npm`, { - env: { ...process.env, CI: 'true' }, - stdio: 'ignore', - cwd: WXT_PACKAGE_DIR, - }), + spawn( + 'pnpm', + ['-s', 'wxt', 'init', project.root, '-t', 'vue', '--pm', 'npm'], + { + env: { CI: 'true' }, + stdio: 'ignore', + cwd: WXT_PACKAGE_DIR, + }, + ), ).rejects.toThrowError('Command failed with exit code 1:'); }); }); diff --git a/packages/wxt/e2e/tests/npm-packages.test.ts b/packages/wxt/e2e/tests/npm-packages.test.ts new file mode 100644 index 00000000..f5d387d3 --- /dev/null +++ b/packages/wxt/e2e/tests/npm-packages.test.ts @@ -0,0 +1,40 @@ +import { test, expect } from 'vitest'; +import spawn from 'nano-spawn'; +import { + NpmListDependency, + NpmListProject, +} from '../../src/core/package-managers/npm'; + +// Tests to ensure the total size of the WXT module is as small as possible +// https://pkg-size.dev/wxt + +test('Only one version of esbuild should be installed (each version is ~20mb of node_modules)', async () => { + const { stdout } = await spawn('pnpm', [ + 'why', + 'esbuild', + '--prod', + '--json', + ]); + const projects: NpmListProject[] = JSON.parse(stdout); + const esbuildVersions = new Set(); + iterateDependencies(projects, (name, meta) => { + if (name === 'esbuild') esbuildVersions.add(meta.version); + }); + + expect([...esbuildVersions]).toHaveLength(1); +}); + +function iterateDependencies( + projects: NpmListProject[], + cb: (name: string, meta: NpmListDependency) => void, +) { + const recurse = (dependencies: Record) => { + Object.entries(dependencies).forEach(([name, meta]) => { + cb(name, meta); + if (meta.dependencies) recurse(meta.dependencies); + }); + }; + projects.forEach((project) => { + if (project.dependencies) recurse(project.dependencies); + }); +} diff --git a/packages/wxt/e2e/tests/user-config.test.ts b/packages/wxt/e2e/tests/user-config.test.ts index 01ac7f4d..c0b49750 100644 --- a/packages/wxt/e2e/tests/user-config.test.ts +++ b/packages/wxt/e2e/tests/user-config.test.ts @@ -130,4 +130,31 @@ describe('User Config', () => { await project.fileExists('.custom-output/chrome-mv3/background.js'), ).toBe(true); }); + + it('should respect outDirTemplate', async () => { + const project = new TestProject(); + project.setConfigFileConfig({ + srcDir: 'src', + outDirTemplate: + 'test-{{browser}}-mv{{manifestVersion}}-{{mode}}{{modeSuffix}}-{{command}}', + }); + project.addFile( + 'src/entrypoints/background.ts', + `export default defineBackground( + () => console.log('Hello background'), + );`, + ); + + await project.build(); + + expect( + await project.fileExists('.output/test-chrome-mv3-production-build'), + ).toBe(true); + + await project.build({ mode: 'development' }); + + expect( + await project.fileExists('.output/test-chrome-mv3-development-dev-build'), + ).toBe(true); + }); }); diff --git a/packages/wxt/e2e/tests/zip.test.ts b/packages/wxt/e2e/tests/zip.test.ts index 5645db60..e20fccc1 100644 --- a/packages/wxt/e2e/tests/zip.test.ts +++ b/packages/wxt/e2e/tests/zip.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest'; import { TestProject } from '../utils'; import extract from 'extract-zip'; -import { execaCommand } from 'execa'; +import spawn from 'nano-spawn'; import { readFile, writeFile } from 'fs-extra'; process.env.WXT_PNPM_IGNORE_WORKSPACE = 'true'; @@ -41,13 +41,15 @@ describe('Zipping', () => { // Build zipped extension await expect( - execaCommand('pnpm i --ignore-workspace --frozen-lockfile false', { + spawn('pnpm', ['i', '--ignore-workspace', '--frozen-lockfile', 'false'], { cwd: unzipDir, }), - ).resolves.toMatchObject({ exitCode: 0 }); + ).resolves.not.toHaveProperty('exitCode'); await expect( - execaCommand('pnpm wxt build -b firefox', { cwd: unzipDir }), - ).resolves.toMatchObject({ exitCode: 0 }); + spawn('pnpm', ['wxt', 'build', '-b', 'firefox'], { + cwd: unzipDir, + }), + ).resolves.not.toHaveProperty('exitCode'); await expect(project.fileExists(unzipDir, '.output')).resolves.toBe(true); expect( @@ -178,4 +180,73 @@ describe('Zipping', () => { true, ); }); + + it.each(['firefox', 'opera'])( + 'should create sources zip for "%s" browser when sourcesZip is undefined', + async (browser) => { + const project = new TestProject({ + name: 'test', + version: '1.0.0', + }); + project.addFile( + 'entrypoints/background.ts', + 'export default defineBackground(() => {});', + ); + const sourcesZip = project.resolvePath('.output/test-1.0.0-sources.zip'); + + await project.zip({ + browser, + }); + + expect(await project.fileExists(sourcesZip)).toBe(true); + }, + ); + + it.each(['firefox', 'chrome'])( + 'should create sources zip for "%s" when sourcesZip is true', + async (browser) => { + const project = new TestProject({ + name: 'test', + version: '1.0.0', + }); + project.addFile( + 'entrypoints/background.ts', + 'export default defineBackground(() => {});', + ); + const sourcesZip = project.resolvePath('.output/test-1.0.0-sources.zip'); + + await project.zip({ + browser, + zip: { + zipSources: true, + }, + }); + + expect(await project.fileExists(sourcesZip)).toBe(true); + }, + ); + + it.each(['firefox', 'chrome'])( + 'should not create sources zip for "%s" when sourcesZip is false', + async (browser) => { + const project = new TestProject({ + name: 'test', + version: '1.0.0', + }); + project.addFile( + 'entrypoints/background.ts', + 'export default defineBackground(() => {});', + ); + const sourcesZip = project.resolvePath('.output/test-1.0.0-sources.zip'); + + await project.zip({ + browser, + zip: { + zipSources: false, + }, + }); + + expect(await project.fileExists(sourcesZip)).toBe(false); + }, + ); }); diff --git a/packages/wxt/e2e/utils.ts b/packages/wxt/e2e/utils.ts index a57943d7..8a44c985 100644 --- a/packages/wxt/e2e/utils.ts +++ b/packages/wxt/e2e/utils.ts @@ -1,7 +1,7 @@ import { dirname, relative, resolve } from 'path'; import fs, { mkdir } from 'fs-extra'; import glob from 'fast-glob'; -import { execaCommand } from 'execa'; +import spawn from 'nano-spawn'; import { InlineConfig, UserConfig, @@ -119,7 +119,7 @@ export class TestProject { await fs.writeFile(filePath, content ?? '', 'utf-8'); } - await execaCommand('pnpm --ignore-workspace i --ignore-scripts', { + await spawn('pnpm', ['--ignore-workspace', 'i', '--ignore-scripts'], { cwd: this.root, }); await mkdir(resolve(this.root, 'public'), { recursive: true }).catch( diff --git a/packages/wxt/package.json b/packages/wxt/package.json index 9ff7f4d8..11259f9e 100644 --- a/packages/wxt/package.json +++ b/packages/wxt/package.json @@ -1,11 +1,11 @@ { "name": "wxt", "type": "module", - "version": "0.19.9", + "version": "0.19.13", "description": "Next gen framework for developing web extensions", "repository": { "type": "git", - "url": "https://github.com/wxt-dev/wxt" + "url": "git+https://github.com/wxt-dev/wxt.git" }, "homepage": "https://wxt.dev", "keywords": [ @@ -72,7 +72,7 @@ "scripts": { "wxt": "tsx src/cli/index.ts", "build": "buildc -- unbuild", - "check": "pnpm build && run-s -c check:*", + "check": "pnpm build && pnpm run --reporter-hide-prefix /^check:.*/", "check:default": "check", "check:tsc-virtual": "tsc --noEmit -p src/virtual", "test": "buildc --deps-only -- vitest", @@ -81,24 +81,24 @@ "prepack": "pnpm build" }, "dependencies": { - "@types/chrome": "^0.0.269", "@aklinker1/rollup-plugin-visualizer": "5.12.0", + "@types/chrome": "^0.0.269", "@types/webextension-polyfill": "^0.10.7", "@webext-core/fake-browser": "^1.3.1", "@webext-core/isolated-element": "^1.1.2", "@webext-core/match-patterns": "^1.0.3", "async-mutex": "^0.5.0", - "c12": "^1.11.1", + "c12": "^1.11.2", "cac": "^6.7.14", "chokidar": "^3.6.0", "ci-info": "^4.0.0", "consola": "^3.2.3", "defu": "^6.1.4", "dequal": "^2.0.3", - "esbuild": "^0.23.0", - "execa": "^9.3.1", + "dotenv": "^16.4.5", + "esbuild": "^0.21.5", "fast-glob": "^3.3.2", - "filesize": "^10.1.4", + "filesize": "^10.1.6", "fs-extra": "^11.2.0", "get-port": "^7.1.0", "giget": "^1.2.3", @@ -107,22 +107,23 @@ "jiti": "^1.21.6", "json5": "^2.2.3", "jszip": "^3.10.1", - "linkedom": "^0.18.4", - "magicast": "^0.3.4", + "linkedom": "^0.18.5", + "magicast": "^0.3.5", "minimatch": "^10.0.1", - "natural-compare": "^1.4.0", + "nano-spawn": "^0.1.0", "normalize-path": "^3.0.0", - "nypm": "^0.3.9", - "ohash": "^1.1.3", + "nypm": "^0.3.12", + "ohash": "^1.1.4", "open": "^10.1.0", "ora": "^8.1.0", - "picocolors": "^1.0.1", + "perfect-debounce": "^1.0.0", + "picocolors": "^1.1.0", "prompts": "^2.4.2", - "publish-browser-extension": "^2.1.3", + "publish-browser-extension": "^2.2.2", "scule": "^1.3.0", - "unimport": "^3.11.1", - "vite": "^5.3.5", - "vite-node": "^2.0.4", + "unimport": "^3.13.1", + "vite": "^5.4.8", + "vite-node": "^2.1.2", "web-ext-run": "^0.2.1", "webextension-polyfill": "^0.12.0" }, @@ -131,20 +132,18 @@ "@faker-js/faker": "^8.4.1", "@types/fs-extra": "^11.0.4", "@types/lodash.merge": "^4.6.9", - "@types/natural-compare": "^1.4.3", - "@types/node": "^20.14.12", + "@types/node": "^20.16.10", "@types/normalize-path": "^3.0.2", "@types/prompts": "^2.4.9", "extract-zip": "^2.0.1", "happy-dom": "^14.12.3", "lodash.merge": "^4.6.2", - "oxlint": "^0.9.1", - "p-map": "^7.0.2", - "publint": "^0.2.9", + "oxlint": "^0.9.9", + "publint": "^0.2.11", "tsx": "4.15.7", - "typescript": "^5.5.4", + "typescript": "^5.6.2", "unbuild": "^2.0.0", - "vitest": "^2.0.4", + "vitest": "^2.1.2", "vitest-plugin-random-seed": "^1.1.0" }, "peerDependenciesMeta": { diff --git a/packages/wxt/src/__tests__/storage.test.ts b/packages/wxt/src/__tests__/storage.test.ts index 6d3e838d..d5fae852 100644 --- a/packages/wxt/src/__tests__/storage.test.ts +++ b/packages/wxt/src/__tests__/storage.test.ts @@ -903,5 +903,24 @@ describe('Storage Utils', () => { // @ts-expect-error await storage.getItem('loca:test').catch(() => {}); }); + + it('should return a nullable type when getItem is called without a fallback', async () => { + const res = await storage.getItem('local:test'); + expectTypeOf(res).toBeNullable(); + }); + + it('should return a non-null type when getItem is called with a fallback', async () => { + const res = await storage.getItem('local:test', { + fallback: 'test', + }); + expectTypeOf(res).not.toBeNullable(); + }); + + it('should return a non-null type when getItem is called with a fallback and the first type parameter is passed', async () => { + const res = await storage.getItem('local:test', { + fallback: 'test', + }); + expectTypeOf(res).not.toBeNullable(); + }); }); }); 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/browser/index.ts b/packages/wxt/src/browser/index.ts index eeb0a4f3..3eb44e11 100644 --- a/packages/wxt/src/browser/index.ts +++ b/packages/wxt/src/browser/index.ts @@ -11,13 +11,17 @@ export type AugmentedBrowser = Omit & { i18n: WxtI18n & Omit; }; -export interface WxtRuntime { - // Overriden per-project -} +/** + * This interface is empty because it is generated per-project when running `wxt prepare`. See: + * - `.wxt/types/paths.d.ts` + */ +export interface WxtRuntime {} -export interface WxtI18n { - // Overriden per-project -} +/** + * This interface is empty because it is generated per-project when running `wxt prepare`. See: + * - `.wxt/types/i18n.d.ts` + */ +export interface WxtI18n {} export const browser: AugmentedBrowser = originalBrowser; diff --git a/packages/wxt/src/cli/__tests__/index.test.ts b/packages/wxt/src/cli/__tests__/index.test.ts index 6419163b..07493433 100644 --- a/packages/wxt/src/cli/__tests__/index.test.ts +++ b/packages/wxt/src/cli/__tests__/index.test.ts @@ -237,7 +237,9 @@ describe('CLI', () => { mockArgv('zip'); await importCli(); - expect(zipMock).toBeCalledWith({}); + expect(zipMock).toBeCalledWith({ + zip: {}, + }); }); it('should respect passing a custom root', async () => { @@ -246,6 +248,7 @@ describe('CLI', () => { expect(zipMock).toBeCalledWith({ root: 'path/to/root', + zip: {}, }); }); @@ -255,6 +258,7 @@ describe('CLI', () => { expect(zipMock).toBeCalledWith({ configFile: './path/to/config.ts', + zip: {}, }); }); @@ -264,6 +268,7 @@ describe('CLI', () => { expect(zipMock).toBeCalledWith({ mode: 'development', + zip: {}, }); }); @@ -273,6 +278,7 @@ describe('CLI', () => { expect(zipMock).toBeCalledWith({ browser: 'firefox', + zip: {}, }); }); @@ -282,6 +288,7 @@ describe('CLI', () => { expect(zipMock).toBeCalledWith({ manifestVersion: 2, + zip: {}, }); }); @@ -291,6 +298,7 @@ describe('CLI', () => { expect(zipMock).toBeCalledWith({ manifestVersion: 3, + zip: {}, }); }); @@ -300,6 +308,40 @@ describe('CLI', () => { expect(zipMock).toBeCalledWith({ debug: true, + zip: {}, + }); + }); + + it('should pass undefined for zipSources when --sources is not passed', async () => { + mockArgv('zip'); + await importCli(); + + expect(zipMock).toBeCalledWith({ + zip: { + zipSources: undefined, + }, + }); + }); + + it('should pass true for zipSources when --sources is passed', async () => { + mockArgv('zip', '--sources'); + await importCli(); + + expect(zipMock).toBeCalledWith({ + zip: { + zipSources: true, + }, + }); + }); + + it('should pass false for zipSources when --sources=false is passed', async () => { + mockArgv('zip', '--sources=false'); + await importCli(); + + expect(zipMock).toBeCalledWith({ + zip: { + zipSources: false, + }, }); }); }); diff --git a/packages/wxt/src/cli/cli-utils.ts b/packages/wxt/src/cli/cli-utils.ts index 952416a1..2f525ae6 100644 --- a/packages/wxt/src/cli/cli-utils.ts +++ b/packages/wxt/src/cli/cli-utils.ts @@ -5,6 +5,7 @@ import { printHeader } from '../core/utils/log'; import { formatDuration } from '../core/utils/time'; import { ValidationError } from '../core/utils/validation'; import { registerWxt } from '../core/wxt'; +import spawn from 'nano-spawn'; /** * Wrap an action handler to add a timer, error handling, and maybe enable debug mode. @@ -87,8 +88,7 @@ export function createAliasedCommand( const args = process.argv.slice( process.argv.indexOf(aliasedCommand.name) + 1, ); - const { execa } = await import('execa'); - await execa(bin, args, { + await spawn(bin, args, { stdio: 'inherit', }); } catch { diff --git a/packages/wxt/src/cli/commands.ts b/packages/wxt/src/cli/commands.ts index 75b02947..a6159881 100644 --- a/packages/wxt/src/cli/commands.ts +++ b/packages/wxt/src/cli/commands.ts @@ -95,6 +95,7 @@ cli .option('-b, --browser ', 'specify a browser') .option('--mv3', 'target manifest v3') .option('--mv2', 'target manifest v2') + .option('--sources', 'always create sources zip') .action( wrapAction(async (root, flags) => { await zip({ @@ -104,6 +105,9 @@ cli manifestVersion: flags.mv3 ? 3 : flags.mv2 ? 2 : undefined, configFile: flags.config, debug: flags.debug, + zip: { + zipSources: flags.sources, + }, }); }), ); diff --git a/packages/wxt/src/client/content-scripts/content-script-context.ts b/packages/wxt/src/client/content-scripts/content-script-context.ts index 38cb9ed3..4474ca46 100644 --- a/packages/wxt/src/client/content-scripts/content-script-context.ts +++ b/packages/wxt/src/client/content-scripts/content-script-context.ts @@ -37,30 +37,30 @@ import { createLocationWatcher } from './location-watcher'; export class ContentScriptContext implements AbortController { private static SCRIPT_STARTED_MESSAGE_TYPE = 'wxt:content-script-started'; - #isTopFrame = window.self === window.top; - #abortController: AbortController; - #locationWatcher = createLocationWatcher(this); + private isTopFrame = window.self === window.top; + private abortController: AbortController; + private locationWatcher = createLocationWatcher(this); constructor( private readonly contentScriptName: string, public readonly options?: Omit, ) { - this.#abortController = new AbortController(); + this.abortController = new AbortController(); - if (this.#isTopFrame) { - this.#listenForNewerScripts({ ignoreFirstEvent: true }); - this.#stopOldScripts(); + if (this.isTopFrame) { + this.listenForNewerScripts({ ignoreFirstEvent: true }); + this.stopOldScripts(); } else { - this.#listenForNewerScripts(); + this.listenForNewerScripts(); } } get signal() { - return this.#abortController.signal; + return this.abortController.signal; } abort(reason?: any): void { - return this.#abortController.abort(reason); + return this.abortController.abort(reason); } get isInvalid(): boolean { @@ -188,7 +188,7 @@ export class ContentScriptContext implements AbortController { ) { if (type === 'wxt:locationchange') { // Start the location watcher when adding the event for the first time - if (this.isValid) this.#locationWatcher.run(); + if (this.isValid) this.locationWatcher.run(); } target.addEventListener?.( @@ -213,7 +213,7 @@ export class ContentScriptContext implements AbortController { ); } - #stopOldScripts() { + stopOldScripts() { // Use postMessage so it get's sent to all the frames of the page. window.postMessage( { @@ -224,7 +224,7 @@ export class ContentScriptContext implements AbortController { ); } - #listenForNewerScripts(options?: { ignoreFirstEvent?: boolean }) { + listenForNewerScripts(options?: { ignoreFirstEvent?: boolean }) { let isFirst = true; const cb = (event: MessageEvent) => { 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..6ab15ab4 100644 --- a/packages/wxt/src/core/builders/vite/index.ts +++ b/packages/wxt/src/core/builders/vite/index.ts @@ -44,6 +44,7 @@ export async function createViteBuilder( config.configFile = false; config.logLevel = 'warn'; config.mode = wxtConfig.mode; + config.envPrefix ??= ['VITE_', 'WXT_']; config.build ??= {}; config.publicDir = wxtConfig.publicDir; @@ -111,7 +112,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/create-server.ts b/packages/wxt/src/core/create-server.ts index d680d82a..aa834ae0 100644 --- a/packages/wxt/src/core/create-server.ts +++ b/packages/wxt/src/core/create-server.ts @@ -1,3 +1,4 @@ +import { debounce } from 'perfect-debounce'; import { BuildStepOutput, EntrypointGroup, @@ -144,7 +145,7 @@ function createFileReloader(server: WxtDevServer) { const fileChangedMutex = new Mutex(); const changeQueue: Array<[string, string]> = []; - return async (event: string, path: string) => { + const cb = async (event: string, path: string) => { changeQueue.push([event, path]); await fileChangedMutex.runExclusive(async () => { @@ -216,6 +217,11 @@ function createFileReloader(server: WxtDevServer) { } }); }; + + return debounce(cb, wxt.config.dev.server!.watchDebounce, { + leading: true, + trailing: false, + }); } /** diff --git a/packages/wxt/src/core/utils/building/generate-wxt-dir.ts b/packages/wxt/src/core/generate-wxt-dir.ts similarity index 92% rename from packages/wxt/src/core/utils/building/generate-wxt-dir.ts rename to packages/wxt/src/core/generate-wxt-dir.ts index 5d388f6d..cf9980c7 100644 --- a/packages/wxt/src/core/utils/building/generate-wxt-dir.ts +++ b/packages/wxt/src/core/generate-wxt-dir.ts @@ -1,23 +1,18 @@ -import { Entrypoint, WxtDirEntry, WxtDirFileEntry } from '../../../types'; +import { Entrypoint, WxtDirEntry, WxtDirFileEntry } from '../types'; import fs from 'fs-extra'; import { dirname, relative, resolve } from 'node:path'; -import { - getEntrypointBundlePath, - isHtmlEntrypoint, -} from '../../utils/entrypoints'; -import { getEntrypointGlobals, getGlobals } from '../../utils/globals'; -import { normalizePath } from '../../utils/paths'; +import { getEntrypointBundlePath, isHtmlEntrypoint } from './utils/entrypoints'; +import { getEntrypointGlobals, getGlobals } from './utils/globals'; +import { normalizePath } from './utils/paths'; import path from 'node:path'; -import { Message, parseI18nMessages } from '../../utils/i18n'; -import { writeFileIfDifferent, getPublicFiles } from '../../utils/fs'; -import { wxt } from '../../wxt'; +import { Message, parseI18nMessages } from './utils/i18n'; +import { writeFileIfDifferent, getPublicFiles } from './utils/fs'; +import { wxt } from './wxt'; /** * Generate and write all the files inside the `InternalConfig.typesDir` directory. */ -export async function generateTypesDir( - entrypoints: Entrypoint[], -): Promise { +export async function generateWxtDir(entrypoints: Entrypoint[]): Promise { await fs.ensureDir(wxt.config.typesDir); const entries: WxtDirEntry[] = [ @@ -27,7 +22,7 @@ export async function generateTypesDir( // 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/core/package-managers/__tests__/npm.test.ts b/packages/wxt/src/core/package-managers/__tests__/npm.test.ts index 5e27e3e1..de2e8e2a 100644 --- a/packages/wxt/src/core/package-managers/__tests__/npm.test.ts +++ b/packages/wxt/src/core/package-managers/__tests__/npm.test.ts @@ -1,7 +1,7 @@ import { beforeAll, describe, expect, it } from 'vitest'; import path from 'node:path'; import { npm } from '../npm'; -import { execaCommand } from 'execa'; +import spawn from 'nano-spawn'; import { exists } from 'fs-extra'; describe('NPM Package Management Utils', () => { @@ -9,7 +9,7 @@ describe('NPM Package Management Utils', () => { const cwd = path.resolve(__dirname, 'fixtures/simple-npm-project'); beforeAll(async () => { // NPM needs the modules installed for 'npm ls' to work - await execaCommand('npm i', { cwd }); + await spawn('npm', ['i'], { cwd }); }, 60e3); it('should list direct dependencies', async () => { diff --git a/packages/wxt/src/core/package-managers/__tests__/pnpm.test.ts b/packages/wxt/src/core/package-managers/__tests__/pnpm.test.ts index 34b48811..20b6312c 100644 --- a/packages/wxt/src/core/package-managers/__tests__/pnpm.test.ts +++ b/packages/wxt/src/core/package-managers/__tests__/pnpm.test.ts @@ -1,7 +1,7 @@ import { beforeAll, describe, expect, it } from 'vitest'; import path from 'node:path'; import { pnpm } from '../pnpm'; -import { execaCommand } from 'execa'; +import spawn from 'nano-spawn'; process.env.WXT_PNPM_IGNORE_WORKSPACE = 'true'; @@ -10,7 +10,7 @@ describe('PNPM Package Management Utils', () => { const cwd = path.resolve(__dirname, 'fixtures/simple-pnpm-project'); beforeAll(async () => { // PNPM needs the modules installed, or 'pnpm ls' will return a blank list. - await execaCommand('pnpm i --ignore-workspace', { cwd }); + await spawn('pnpm', ['i', '--ignore-workspace'], { cwd }); }); it('should list direct dependencies', async () => { diff --git a/packages/wxt/src/core/package-managers/bun.ts b/packages/wxt/src/core/package-managers/bun.ts index 8296c015..e06882d1 100644 --- a/packages/wxt/src/core/package-managers/bun.ts +++ b/packages/wxt/src/core/package-managers/bun.ts @@ -1,5 +1,6 @@ import { dedupeDependencies, npm } from './npm'; import { WxtPackageManagerImpl } from './types'; +import spawn from 'nano-spawn'; export const bun: WxtPackageManagerImpl = { overridesKey: 'overrides', // But also supports "resolutions" @@ -11,8 +12,7 @@ export const bun: WxtPackageManagerImpl = { if (options?.all) { args.push('--all'); } - const { execa } = await import('execa'); - const res = await execa('bun', args, { cwd: options?.cwd }); + const res = await spawn('bun', args, { cwd: options?.cwd }); return dedupeDependencies( res.stdout .split('\n') diff --git a/packages/wxt/src/core/package-managers/npm.ts b/packages/wxt/src/core/package-managers/npm.ts index 4137b962..7ad5386f 100644 --- a/packages/wxt/src/core/package-managers/npm.ts +++ b/packages/wxt/src/core/package-managers/npm.ts @@ -2,13 +2,13 @@ import { Dependency } from '../../types'; import { WxtPackageManagerImpl } from './types'; import path from 'node:path'; import { ensureDir } from 'fs-extra'; +import spawn from 'nano-spawn'; export const npm: WxtPackageManagerImpl = { overridesKey: 'overrides', async downloadDependency(id, downloadDir) { await ensureDir(downloadDir); - const { execa } = await import('execa'); - const res = await execa('npm', ['pack', id, '--json'], { + const res = await spawn('npm', ['pack', id, '--json'], { cwd: downloadDir, }); const packed: PackedDependency[] = JSON.parse(res.stdout); @@ -19,8 +19,7 @@ export const npm: WxtPackageManagerImpl = { if (options?.all) { args.push('--depth', 'Infinity'); } - const { execa } = await import('execa'); - const res = await execa('npm', args, { cwd: options?.cwd }); + const res = await spawn('npm', args, { cwd: options?.cwd }); const project: NpmListProject = JSON.parse(res.stdout); return flattenNpmListOutput([project]); diff --git a/packages/wxt/src/core/package-managers/pnpm.ts b/packages/wxt/src/core/package-managers/pnpm.ts index 891fe18a..32d89b60 100644 --- a/packages/wxt/src/core/package-managers/pnpm.ts +++ b/packages/wxt/src/core/package-managers/pnpm.ts @@ -1,5 +1,6 @@ import { NpmListProject, flattenNpmListOutput, npm } from './npm'; import { WxtPackageManagerImpl } from './types'; +import spawn from 'nano-spawn'; export const pnpm: WxtPackageManagerImpl = { overridesKey: 'resolutions', // "pnpm.overrides" has a higher priority, but I don't want to deal with nesting @@ -19,8 +20,7 @@ export const pnpm: WxtPackageManagerImpl = { ) { args.push('--ignore-workspace'); } - const { execa } = await import('execa'); - const res = await execa('pnpm', args, { cwd: options?.cwd }); + const res = await spawn('pnpm', args, { cwd: options?.cwd }); const projects: NpmListProject[] = JSON.parse(res.stdout); return flattenNpmListOutput(projects); diff --git a/packages/wxt/src/core/package-managers/yarn.ts b/packages/wxt/src/core/package-managers/yarn.ts index c313ca8d..8b544932 100644 --- a/packages/wxt/src/core/package-managers/yarn.ts +++ b/packages/wxt/src/core/package-managers/yarn.ts @@ -1,6 +1,7 @@ import { Dependency } from '../../types'; import { WxtPackageManagerImpl } from './types'; import { dedupeDependencies, npm } from './npm'; +import spawn from 'nano-spawn'; export const yarn: WxtPackageManagerImpl = { overridesKey: 'resolutions', @@ -12,8 +13,7 @@ export const yarn: WxtPackageManagerImpl = { if (options?.all) { args.push('--depth', 'Infinity'); } - const { execa } = await import('execa'); - const res = await execa('yarn', args, { cwd: options?.cwd }); + const res = await spawn('yarn', args, { cwd: options?.cwd }); const tree = res.stdout .split('\n') .map((line) => JSON.parse(line)) diff --git a/packages/wxt/src/core/prepare.ts b/packages/wxt/src/core/prepare.ts index 90e66c72..f5bcfa37 100644 --- a/packages/wxt/src/core/prepare.ts +++ b/packages/wxt/src/core/prepare.ts @@ -1,5 +1,6 @@ import { InlineConfig } from '../types'; -import { findEntrypoints, generateTypesDir } from './utils/building'; +import { findEntrypoints } from './utils/building'; +import { generateWxtDir } from './generate-wxt-dir'; import { registerWxt, wxt } from './wxt'; export async function prepare(config: InlineConfig) { @@ -7,5 +8,5 @@ export async function prepare(config: InlineConfig) { wxt.logger.info('Generating types...'); const entrypoints = await findEntrypoints(); - await generateTypesDir(entrypoints); + await generateWxtDir(entrypoints); } diff --git a/packages/wxt/src/core/utils/building/resolve-config.ts b/packages/wxt/src/core/resolve-config.ts similarity index 91% rename from packages/wxt/src/core/utils/building/resolve-config.ts rename to packages/wxt/src/core/resolve-config.ts index aebfa516..dc93a319 100644 --- a/packages/wxt/src/core/utils/building/resolve-config.ts +++ b/packages/wxt/src/core/resolve-config.ts @@ -14,17 +14,19 @@ import { WxtModuleWithMetadata, ResolvedEslintrc, Eslintrc, -} from '../../../types'; +} from '../types'; import path from 'node:path'; -import { createFsCache } from '../../utils/cache'; +import { createFsCache } from './utils/cache'; import consola, { LogLevels } from 'consola'; import defu from 'defu'; -import { NullablyRequired } from '../types'; +import { NullablyRequired } from './utils/types'; import fs from 'fs-extra'; -import { normalizePath } from '../paths'; +import { normalizePath } from './utils/paths'; import glob from 'fast-glob'; -import { builtinModules } from '../../../builtin-modules'; -import { getEslintVersion } from '../eslint'; +import { builtinModules } from '../builtin-modules'; +import { getEslintVersion } from './utils/eslint'; +import { safeStringToNumber } from './utils/number'; +import { loadEnv } from './utils/env'; /** * Given an inline config, discover the config file if necessary, merge the results, resolve any @@ -72,6 +74,8 @@ export async function resolveConfig( const mode = mergedConfig.mode ?? COMMAND_MODES[command]; const env: ConfigEnv = { browser, command, manifestVersion, mode }; + loadEnv(mode, browser); // Load any environment variables used below + const root = path.resolve( inlineConfig.root ?? userConfig.root ?? process.cwd(), ); @@ -92,7 +96,21 @@ export async function resolveConfig( const publicDir = path.resolve(srcDir, mergedConfig.publicDir ?? 'public'); const typesDir = path.resolve(wxtDir, 'types'); const outBaseDir = path.resolve(root, mergedConfig.outDir ?? '.output'); - const outDir = path.resolve(outBaseDir, `${browser}-mv${manifestVersion}`); + const modeSuffixes: Record = { + production: '', + development: '-dev', + }; + const outDirTemplate = ( + mergedConfig.outDirTemplate ?? `${browser}-mv${manifestVersion}` + ) + // Resolve all variables in the template + .replaceAll('{{browser}}', browser) + .replaceAll('{{manifestVersion}}', manifestVersion.toString()) + .replaceAll('{{modeSuffix}}', modeSuffixes[mode] ?? `-${mode}`) + .replaceAll('{{mode}}', mode) + .replaceAll('{{command}}', command); + + const outDir = path.resolve(outBaseDir, outDirTemplate); const reloadCommand = mergedConfig.dev?.reloadCommand ?? 'Alt+R'; const runnerConfig = await loadConfig({ @@ -124,6 +142,7 @@ export async function resolveConfig( devServerConfig = { port, hostname: mergedConfig.dev?.server?.hostname ?? 'localhost', + watchDebounce: safeStringToNumber(process.env.WXT_WATCH_DEBOUNCE) ?? 800, }; } @@ -174,7 +193,7 @@ export async function resolveConfig( srcDir, typesDir, wxtDir, - zip: resolveZipConfig(root, outBaseDir, mergedConfig), + zip: resolveZipConfig(root, browser, outBaseDir, mergedConfig), transformManifest: mergedConfig.transformManifest, analysis: resolveAnalysisConfig(root, mergedConfig), userConfigMetadata: userConfigMetadata ?? {}, @@ -253,6 +272,7 @@ async function mergeInlineConfig( function resolveZipConfig( root: string, + browser: string, outBaseDir: string, mergedConfig: InlineConfig, ): NullablyRequired { @@ -265,6 +285,8 @@ function resolveZipConfig( includeSources: [], compressionLevel: 9, ...mergedConfig.zip, + zipSources: + mergedConfig.zip?.zipSources ?? ['firefox', 'opera'].includes(browser), exclude: mergedConfig.zip?.exclude ?? [], excludeSources: [ '**/node_modules', @@ -472,6 +494,8 @@ export async function resolveWxtUserModules( cwd: modulesDir, onlyFiles: true, }).catch(() => []); + // Sort modules to ensure a consistent execution order + localModulePaths.sort(); const localModules = await Promise.all>( localModulePaths.map(async (file) => { const absolutePath = normalizePath(path.resolve(modulesDir, file)); diff --git a/packages/wxt/src/core/utils/__tests__/number.test.ts b/packages/wxt/src/core/utils/__tests__/number.test.ts new file mode 100644 index 00000000..ae345096 --- /dev/null +++ b/packages/wxt/src/core/utils/__tests__/number.test.ts @@ -0,0 +1,18 @@ +import { describe, it, expect } from 'vitest'; +import { safeStringToNumber } from '../number'; + +describe('Number Utils', () => { + describe('safeStringToNumber', () => { + it.each([ + { arg: '1000', expected: 1000 }, + { arg: '', expected: 0 }, + { arg: '12abc', expected: null }, + { arg: undefined, expected: null }, + ])( + 'should be safely converted from string to number: safeStringToNumber($arg) -> $expected', + ({ arg, expected }) => { + expect(safeStringToNumber(arg)).toBe(expected); + }, + ); + }); +}); diff --git a/packages/wxt/src/core/utils/building/index.ts b/packages/wxt/src/core/utils/building/index.ts index 16bd6d03..72d74acd 100644 --- a/packages/wxt/src/core/utils/building/index.ts +++ b/packages/wxt/src/core/utils/building/index.ts @@ -1,8 +1,6 @@ export * from './build-entrypoints'; export * from './detect-dev-changes'; export * from './find-entrypoints'; -export * from './generate-wxt-dir'; -export * from './resolve-config'; export * from './group-entrypoints'; export * from './import-entrypoint'; export * from './internal-build'; diff --git a/packages/wxt/src/core/utils/building/rebuild.ts b/packages/wxt/src/core/utils/building/rebuild.ts index 711dd7d7..7a17e3ff 100644 --- a/packages/wxt/src/core/utils/building/rebuild.ts +++ b/packages/wxt/src/core/utils/building/rebuild.ts @@ -1,6 +1,6 @@ import type { Manifest } from 'wxt/browser'; import { BuildOutput, Entrypoint, EntrypointGroup } from '../../../types'; -import { generateTypesDir } from './generate-wxt-dir'; +import { generateWxtDir } from '../../generate-wxt-dir'; import { buildEntrypoints } from './build-entrypoints'; import { generateManifest, writeManifest } from '../../utils/manifest'; import { wxt } from '../../wxt'; @@ -37,7 +37,7 @@ export async function rebuild( const spinner = ora(`Preparing...`).start(); // Update types directory with new files and types - await generateTypesDir(allEntrypoints).catch((err) => { + await generateWxtDir(allEntrypoints).catch((err) => { wxt.logger.warn('Failed to update .wxt directory:', err); // Throw the error if doing a regular build, don't for dev mode. if (wxt.config.command === 'build') throw err; diff --git a/packages/wxt/src/core/utils/env.ts b/packages/wxt/src/core/utils/env.ts new file mode 100644 index 00000000..cd189ab2 --- /dev/null +++ b/packages/wxt/src/core/utils/env.ts @@ -0,0 +1,21 @@ +import { config } from 'dotenv'; +import type { TargetBrowser } from '../../types'; + +/** + * Load environment files based on the current mode and browser. + */ +export function loadEnv(mode: string, browser: TargetBrowser) { + return config({ + // Files on top override files below + path: [ + `.env.${mode}.${browser}.local`, + `.env.${mode}.${browser}`, + `.env.${browser}.local`, + `.env.${browser}`, + `.env.${mode}.local`, + `.env.${mode}`, + `.env.local`, + `.env`, + ], + }); +} diff --git a/packages/wxt/src/core/utils/number.ts b/packages/wxt/src/core/utils/number.ts new file mode 100644 index 00000000..ef752a22 --- /dev/null +++ b/packages/wxt/src/core/utils/number.ts @@ -0,0 +1,4 @@ +export function safeStringToNumber(str: string | undefined): number | null { + const num = Number(str); + return isNaN(num) ? null : num; +} diff --git a/packages/wxt/src/core/utils/testing/fake-objects.ts b/packages/wxt/src/core/utils/testing/fake-objects.ts index 08844529..c097aeab 100644 --- a/packages/wxt/src/core/utils/testing/fake-objects.ts +++ b/packages/wxt/src/core/utils/testing/fake-objects.ts @@ -293,6 +293,7 @@ export const fakeResolvedConfig = fakeObjectCreator(() => { downloadedPackagesDir: fakeDir(), downloadPackages: [], compressionLevel: 9, + zipSources: false, }, transformManifest: () => {}, userConfigMetadata: {}, diff --git a/packages/wxt/src/core/wxt.ts b/packages/wxt/src/core/wxt.ts index 5674e772..a95c27ae 100644 --- a/packages/wxt/src/core/wxt.ts +++ b/packages/wxt/src/core/wxt.ts @@ -7,11 +7,12 @@ import { WxtHooks, WxtModule, } from '../types'; -import { resolveConfig } from './utils/building'; +import { resolveConfig } from './resolve-config'; import { createHooks } from 'hookable'; import { createWxtPackageManager } from './package-managers'; import { createViteBuilder } from './builders/vite'; import { builtinModules } from '../builtin-modules'; +import { relative } from 'path'; /** * Global variable set once `createWxt` is called once. Since this variable is used everywhere, this @@ -66,6 +67,20 @@ export async function registerWxt( // Initialize hooks wxt.hooks.addHooks(config.hooks); + if (wxt.config.debug) { + const order = [ + ...builtinModules.map((module) => module.name), + ...config.userModules.map((module) => + relative(wxt.config.root, module.id), + ), + 'wxt.config.ts > hooks', + ]; + wxt.logger.debug('Hook execution order:'); + order.forEach((name, i) => { + wxt.logger.debug(` ${i + 1}. ${name}`); + }); + } + await wxt.hooks.callHook('ready', wxt); } diff --git a/packages/wxt/src/core/zip.ts b/packages/wxt/src/core/zip.ts index 9226a48f..72e6a8a2 100644 --- a/packages/wxt/src/core/zip.ts +++ b/packages/wxt/src/core/zip.ts @@ -20,6 +20,7 @@ import { normalizePath } from './utils/paths'; export async function zip(config?: InlineConfig): Promise { await registerWxt('build', config); const output = await internalBuild(); + await wxt.hooks.callHook('zip:start', wxt); const start = Date.now(); wxt.logger.info('Zipping extension...'); @@ -27,7 +28,9 @@ export async function zip(config?: InlineConfig): Promise { const projectName = wxt.config.zip.name ?? - safeFilename((await getPackageJson())?.name || path.dirname(process.cwd())); + safeFilename( + (await getPackageJson())?.name || path.basename(process.cwd()), + ); const applyTemplate = (template: string): string => template .replaceAll('{{name}}', projectName) @@ -42,17 +45,17 @@ export async function zip(config?: InlineConfig): Promise { await fs.ensureDir(wxt.config.outBaseDir); // ZIP output directory - + await wxt.hooks.callHook('zip:extension:start', wxt); const outZipFilename = applyTemplate(wxt.config.zip.artifactTemplate); const outZipPath = path.resolve(wxt.config.outBaseDir, outZipFilename); await zipDir(wxt.config.outDir, outZipPath, { exclude: wxt.config.zip.exclude, }); zipFiles.push(outZipPath); + await wxt.hooks.callHook('zip:extension:done', wxt, outZipPath); - // ZIP sources for Firefox - - if (wxt.config.browser === 'firefox') { + if (wxt.config.zip.zipSources) { + await wxt.hooks.callHook('zip:sources:start', wxt); const { overrides, files: downloadedPackages } = await downloadPrivatePackages(); const sourcesZipFilename = applyTemplate(wxt.config.zip.sourcesTemplate); @@ -71,6 +74,7 @@ export async function zip(config?: InlineConfig): Promise { additionalFiles: downloadedPackages, }); zipFiles.push(sourcesZipPath); + await wxt.hooks.callHook('zip:sources:done', wxt, sourcesZipPath); } await printFileList( @@ -80,8 +84,11 @@ export async function zip(config?: InlineConfig): Promise { zipFiles, ); + await wxt.hooks.callHook('zip:done', wxt, zipFiles); + return zipFiles; } + async function zipDir( directory: string, outputPath: string, diff --git a/packages/wxt/src/storage.ts b/packages/wxt/src/storage.ts index 1450912e..55795d4a 100644 --- a/packages/wxt/src/storage.ts +++ b/packages/wxt/src/storage.ts @@ -461,7 +461,16 @@ export interface WxtStorage { * @example * await storage.getItem("local:installDate"); */ - getItem(key: StorageItemKey, opts?: GetItemOptions): Promise; + getItem( + key: StorageItemKey, + opts: GetItemOptions & { fallback: TValue }, + ): Promise; + + getItem( + key: StorageItemKey, + opts?: GetItemOptions, + ): Promise; + /** * Get multiple items from storage. The return order is guaranteed to be the same as the order * requested. diff --git a/packages/wxt/src/types.ts b/packages/wxt/src/types.ts index a95c3fff..3ad48acf 100644 --- a/packages/wxt/src/types.ts +++ b/packages/wxt/src/types.ts @@ -53,6 +53,19 @@ export interface InlineConfig { * @default ".output" */ outDir?: string; + /** + * Template string for customizing the output directory structure. + * Available variables: + * - `{{browser}}`: The target browser (e.g., 'chrome', 'firefox') + * - `{{manifestVersion}}`: The manifest version (e.g., 2 or 3) + * - `{{mode}}`: The build mode (e.g., 'development', 'production') + * - `{{modeSuffix}}`: A suffix based on the mode ('-dev' for development, '' for production) + * - `{{command}}`: The WXT command being run (e.g., 'build', 'serve') + * + * @example "{{browser}}-mv{{manifestVersion}}{{modeSuffix}}" + * @default `"{{browser}}-mv{{manifestVersion}}"` + */ + outDirTemplate?: string; /** * > Only available when using the JS API. Not available in `wxt.config.ts` files * @@ -62,7 +75,7 @@ export interface InlineConfig { */ configFile?: string | false; /** - * Set to `true` to show debug logs. Overriden by the command line `--debug` option. + * Set to `true` to show debug logs. Overridden by the command line `--debug` option. * * @default false */ @@ -130,6 +143,16 @@ export interface InlineConfig { * @default "{{name}}-{{version}}-{{browser}}.zip" */ artifactTemplate?: string; + /** + * When zipping the extension, also zip sources. + * + * - `undefined`: zip sources if the target browser is "firefox" or "opera" + * - `true`: always zip sources + * - `false`: never zip sources + * + * @default undefined + */ + zipSources?: boolean; /** * Configure the filename output when zipping files. * @@ -306,7 +329,7 @@ export interface InlineConfig { * Which extension API to use. * * - `"webextension-polyfill"`: Use `browser` and types from [`webextension-polyfill`](https://www.npmjs.com/package/webextension-polyfill). - * - `"chrome"` (unstable): Use the regular `chrome` (or `browser` for Firefox/Safari) globals provided by the browser. Types provided by [`@types/chrome`](https://www.npmjs.com/package/@types/chrome), make sure to install the package or types won't work. + * - `"chrome"`: Use the regular `chrome` (or `browser` for Firefox/Safari) globals provided by the browser. Types provided by [`@types/chrome`](https://www.npmjs.com/package/@types/chrome). * * @default "webextension-polyfill" * @since 0.19.0 @@ -1164,6 +1187,44 @@ export interface WxtHooks { * @param entrypoints The list of files that will be copied into the output directory */ 'build:publicAssets': (wxt: Wxt, files: ResolvedPublicFile[]) => HookResult; + /** + * Called before the zip process starts. + * @param wxt The configured WXT object + */ + 'zip:start': (wxt: Wxt) => HookResult; + + /** + * Called before zipping the extension files. + * @param wxt The configured WXT object + */ + 'zip:extension:start': (wxt: Wxt) => HookResult; + + /** + * Called after zipping the extension files. + * @param wxt The configured WXT object + * @param zipPath The path to the created extension zip file + */ + 'zip:extension:done': (wxt: Wxt, zipPath: string) => HookResult; + + /** + * Called before zipping the source files (for Firefox). + * @param wxt The configured WXT object + */ + 'zip:sources:start': (wxt: Wxt) => HookResult; + + /** + * Called after zipping the source files (for Firefox). + * @param wxt The configured WXT object + * @param zipPath The path to the created sources zip file + */ + 'zip:sources:done': (wxt: Wxt, zipPath: string) => HookResult; + + /** + * Called after the entire zip process is complete. + * @param wxt The configured WXT object + * @param zipFiles An array of paths to all created zip files + */ + 'zip:done': (wxt: Wxt, zipFiles: string[]) => HookResult; } export interface Wxt { @@ -1186,7 +1247,7 @@ export interface Wxt { */ pm: WxtPackageManager; /** - * If the dev server was started, it will be availble. + * If the dev server was started, it will be available. */ server?: WxtDevServer; /** @@ -1247,6 +1308,10 @@ export interface ResolvedConfig { downloadPackages: string[]; compressionLevel: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; exclude: string[]; + /** + * If true, when zipping the extension, also zip the sources. + */ + zipSources: boolean; }; /** * @deprecated Use `build:manifestGenerated` hook instead. @@ -1277,6 +1342,25 @@ export interface ResolvedConfig { server?: { port: number; hostname: string; + /** + * The milliseconds to debounce when a file is saved before reloading. + * The only way to set this option is to set the `WXT_WATCH_DEBOUNCE` + * environment variable, either globally (like in `.bashrc` file) or + * per-project (in `.env` file). + * + * For example: + * ``` + * # ~/.zshrc + * export WXT_WATCH_DEBOUNCE=1000 + * ``` + * or + * ``` + * # .env + * WXT_WATCH_DEBOUNCE=1000 + * ``` + * @default 800 + */ + watchDebounce: number; }; reloadCommand: string | false; }; 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. diff --git a/patches/markdown-it-footnote.md b/patches/markdown-it-footnote.md new file mode 100644 index 00000000..dc985a62 --- /dev/null +++ b/patches/markdown-it-footnote.md @@ -0,0 +1 @@ +Removed sub-ids from rendered links. When you link to the same footnote multiple times, the link would look like `[3.2]` instead of just `[3]`. Didn't like how that looked, so this patch removes that function. diff --git a/patches/markdown-it-footnote.patch b/patches/markdown-it-footnote.patch new file mode 100644 index 00000000..2667c4ed --- /dev/null +++ b/patches/markdown-it-footnote.patch @@ -0,0 +1,79 @@ +diff --git a/dist/index.cjs.js b/dist/index.cjs.js +index 806448c967261a61288f0faa0633a91f77d35968..6812dd84bbbb7176af4115a287677454fa562883 100644 +--- a/dist/index.cjs.js ++++ b/dist/index.cjs.js +@@ -13,14 +13,14 @@ function render_footnote_anchor_name(tokens, idx, options, env /*, slf */) { + } + function render_footnote_caption(tokens, idx /*, options, env, slf */) { + let n = Number(tokens[idx].meta.id + 1).toString(); +- if (tokens[idx].meta.subId > 0) n += `:${tokens[idx].meta.subId}`; ++ // if (tokens[idx].meta.subId > 0) n += `:${tokens[idx].meta.subId}`; + return `[${n}]`; + } + function render_footnote_ref(tokens, idx, options, env, slf) { + const id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf); + const caption = slf.rules.footnote_caption(tokens, idx, options, env, slf); + let refid = id; +- if (tokens[idx].meta.subId > 0) refid += `:${tokens[idx].meta.subId}`; ++ // if (tokens[idx].meta.subId > 0) refid += `:${tokens[idx].meta.subId}`; + return `${caption}`; + } + function render_footnote_block_open(tokens, idx, options) { +@@ -31,7 +31,7 @@ function render_footnote_block_close() { + } + function render_footnote_open(tokens, idx, options, env, slf) { + let id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf); +- if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}`; ++ // if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}`; + return `

  • `; + } + function render_footnote_close() { +@@ -39,7 +39,7 @@ function render_footnote_close() { + } + function render_footnote_anchor(tokens, idx, options, env, slf) { + let id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf); +- if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}`; ++ // if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}`; + + /* ↩ with escape code to prevent display as Apple Emoji on iOS */ + return ` \u21a9\uFE0E`; +diff --git a/index.mjs b/index.mjs +index 48277ca67206f248b9deb0058e9a7d69dbc07702..718e3e527b2513e4f6f59cba9d4526a36d58f6bc 100644 +--- a/index.mjs ++++ b/index.mjs +@@ -17,7 +17,7 @@ function render_footnote_anchor_name (tokens, idx, options, env/*, slf */) { + function render_footnote_caption (tokens, idx/*, options, env, slf */) { + let n = Number(tokens[idx].meta.id + 1).toString() + +- if (tokens[idx].meta.subId > 0) n += `:${tokens[idx].meta.subId}` ++ // if (tokens[idx].meta.subId > 0) n += `:${tokens[idx].meta.subId}` + + return `[${n}]` + } +@@ -27,7 +27,7 @@ function render_footnote_ref (tokens, idx, options, env, slf) { + const caption = slf.rules.footnote_caption(tokens, idx, options, env, slf) + let refid = id + +- if (tokens[idx].meta.subId > 0) refid += `:${tokens[idx].meta.subId}` ++ // if (tokens[idx].meta.subId > 0) refid += `:${tokens[idx].meta.subId}` + + return `${caption}` + } +@@ -45,7 +45,7 @@ function render_footnote_block_close () { + function render_footnote_open (tokens, idx, options, env, slf) { + let id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf) + +- if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}` ++ // if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}` + + return `
  • ` + } +@@ -57,7 +57,7 @@ function render_footnote_close () { + function render_footnote_anchor (tokens, idx, options, env, slf) { + let id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf) + +- if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}` ++ // if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}` + + /* ↩ with escape code to prevent display as Apple Emoji on iOS */ + return ` \u21a9\uFE0E` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8bc71659..b0b6a260 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,49 +4,48 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + markdown-it-footnote: + hash: ue34jdgdx43siqdj557feoepzq + path: patches/markdown-it-footnote.patch + importers: .: devDependencies: '@aklinker1/buildc': - specifier: ^1.1.1 - version: 1.1.1(typescript@5.5.4) + specifier: ^1.1.4 + version: 1.1.4 '@aklinker1/check': specifier: ^1.4.5 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) '@types/fs-extra': specifier: ^11.0.4 version: 11.0.4 '@vitest/coverage-v8': - specifier: ^2.0.4 - version: 2.0.4(vitest@2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8)) + specifier: ^2.1.2 + version: 2.1.2(vitest@2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4)) changelogen: - specifier: ^0.5.5 - version: 0.5.5 + specifier: ^0.5.7 + version: 0.5.7(magicast@0.3.5) consola: specifier: ^3.2.3 version: 3.2.3 - dependency-graph: - specifier: ^1.0.0 - version: 1.0.0 - execa: - specifier: ^9.3.1 - version: 9.3.1 fast-glob: specifier: ^3.3.2 version: 3.3.2 fs-extra: specifier: ^11.2.0 version: 11.2.0 - hasha: - specifier: ^6.0.0 - version: 6.0.0 lint-staged: - specifier: ^15.2.7 - version: 15.2.7 - npm-run-all: - specifier: ^4.1.5 - version: 4.1.5 + specifier: ^15.2.10 + version: 15.2.10 + markdown-it-footnote: + specifier: ^4.0.0 + version: 4.0.0(patch_hash=ue34jdgdx43siqdj557feoepzq) + nano-spawn: + specifier: ^0.1.0 + version: 0.1.0 prettier: specifier: ^3.3.3 version: 3.3.3 @@ -58,31 +57,28 @@ importers: version: 4.15.7 typedoc: specifier: ^0.25.4 - version: 0.25.4(typescript@5.5.4) + version: 0.25.4(typescript@5.6.2) typedoc-plugin-markdown: specifier: 4.0.0-next.23 - version: 4.0.0-next.23(typedoc@0.25.4(typescript@5.5.4)) + version: 4.0.0-next.23(typedoc@0.25.4(typescript@5.6.2)) typedoc-vitepress-theme: specifier: 1.0.0-next.3 - version: 1.0.0-next.3(typedoc-plugin-markdown@4.0.0-next.23(typedoc@0.25.4(typescript@5.5.4))) + version: 1.0.0-next.3(typedoc-plugin-markdown@4.0.0-next.23(typedoc@0.25.4(typescript@5.6.2))) typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 vitepress: - specifier: ^1.3.1 - version: 1.3.1(@algolia/client-search@4.20.0)(@types/node@20.14.12)(@types/react@18.3.3)(postcss@8.4.39)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)(search-insights@2.15.0)(typescript@5.5.4) + specifier: ^1.3.4 + version: 1.3.4(@algolia/client-search@4.20.0)(@types/node@20.16.10)(@types/react@18.3.11)(postcss@8.4.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.4)(search-insights@2.15.0)(typescript@5.6.2) vitest-mock-extended: - specifier: ^2.0.0 - version: 2.0.0(typescript@5.5.4)(vitest@2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8)) + specifier: ^2.0.2 + version: 2.0.2(typescript@5.6.2)(vitest@2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4)) vue: - specifier: ^3.4.34 - version: 3.4.34(typescript@5.5.4) + specifier: ^3.5.11 + version: 3.5.11(typescript@5.6.2) wxt: specifier: workspace:* version: link:packages/wxt - yaml: - specifier: ^2.5.0 - version: 2.5.0 packages/analytics: dependencies: @@ -92,7 +88,7 @@ importers: devDependencies: '@aklinker1/check': specifier: ^1.3.1 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) '@types/chrome': specifier: ^0.0.268 version: 0.0.268 @@ -104,13 +100,13 @@ importers: version: 3.3.3 publint: specifier: ^0.2.8 - version: 0.2.9 + version: 0.2.11 typescript: specifier: ^5.5.2 - version: 5.5.4 + version: 5.6.2 unbuild: specifier: ^2.0.0 - version: 2.0.0(sass@1.77.8)(typescript@5.5.4) + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) wxt: specifier: workspace:* version: link:../wxt @@ -129,19 +125,19 @@ importers: devDependencies: '@aklinker1/check': specifier: ^1.4.5 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) oxlint: - specifier: ^0.9.1 - version: 0.9.1 + specifier: ^0.9.9 + version: 0.9.9 publint: - specifier: ^0.2.9 - version: 0.2.9 + specifier: ^0.2.11 + version: 0.2.11 typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 unbuild: specifier: ^2.0.0 - version: 2.0.0(sass@1.77.8)(typescript@5.5.4) + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) wxt: specifier: workspace:* version: link:../wxt @@ -160,31 +156,31 @@ importers: devDependencies: '@aklinker1/check': specifier: ^1.4.5 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) '@types/chrome': specifier: ^0.0.268 version: 0.0.268 '@types/node': - specifier: ^20.14.2 - version: 20.14.12 + specifier: ^20.16.10 + version: 20.16.10 oxlint: - specifier: ^0.9.1 - version: 0.9.1 + specifier: ^0.9.9 + version: 0.9.9 publint: - specifier: ^0.2.8 - version: 0.2.9 + specifier: ^0.2.11 + version: 0.2.11 typescript: - specifier: ^5.4.5 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 unbuild: specifier: ^2.0.0 - version: 2.0.0(sass@1.77.8)(typescript@5.5.4) + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) vitest: - specifier: ^1.6.0 - version: 1.6.0(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8) + specifier: ^2.0.0 + version: 2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4) vitest-plugin-random-seed: specifier: ^1.1.0 - version: 1.1.0(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) + version: 1.1.0(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) wxt: specifier: workspace:* version: link:../wxt @@ -192,21 +188,21 @@ importers: packages/module-react: dependencies: '@vitejs/plugin-react': - specifier: ^4.3.1 - version: 4.3.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) + specifier: ^4.3.2 + version: 4.3.2(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) devDependencies: '@aklinker1/check': specifier: ^1.4.5 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) '@types/react': - specifier: ^18.3.3 - version: 18.3.3 + specifier: ^18.3.11 + version: 18.3.11 '@types/react-dom': specifier: ^18.3.0 version: 18.3.0 publint: - specifier: ^0.2.9 - version: 0.2.9 + specifier: ^0.2.11 + version: 0.2.11 react: specifier: ^18.3.1 version: 18.3.1 @@ -214,11 +210,11 @@ importers: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 unbuild: specifier: ^2.0.0 - version: 2.0.0(sass@1.77.8)(typescript@5.5.4) + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) wxt: specifier: workspace:* version: link:../wxt @@ -227,23 +223,23 @@ importers: dependencies: vite-plugin-solid: specifier: ^2.10.2 - version: 2.10.2(solid-js@1.8.19)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) + version: 2.10.2(solid-js@1.9.1)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) devDependencies: '@aklinker1/check': specifier: ^1.4.5 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) publint: - specifier: ^0.2.9 - version: 0.2.9 + specifier: ^0.2.11 + version: 0.2.11 solid-js: - specifier: ^1.8.19 - version: 1.8.19 + specifier: ^1.9.1 + version: 1.9.1 typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 unbuild: specifier: ^2.0.0 - version: 2.0.0(sass@1.77.8)(typescript@5.5.4) + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) wxt: specifier: workspace:* version: link:../wxt @@ -251,21 +247,21 @@ importers: packages/module-svelte: dependencies: '@sveltejs/vite-plugin-svelte': - specifier: ^3.1.1 - version: 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) + specifier: ^3.1.2 + version: 3.1.2(svelte@4.2.18)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) devDependencies: '@aklinker1/check': specifier: ^1.4.5 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) publint: - specifier: ^0.2.9 - version: 0.2.9 + specifier: ^0.2.11 + version: 0.2.11 typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 unbuild: specifier: ^2.0.0 - version: 2.0.0(sass@1.77.8)(typescript@5.5.4) + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) wxt: specifier: workspace:* version: link:../wxt @@ -273,21 +269,52 @@ importers: packages/module-vue: dependencies: '@vitejs/plugin-vue': - specifier: ^5.1.1 - version: 5.1.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8))(vue@3.4.34(typescript@5.5.4)) + specifier: ^5.1.4 + version: 5.1.4(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))(vue@3.5.11(typescript@5.6.2)) devDependencies: '@aklinker1/check': specifier: ^1.4.5 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) publint: - specifier: ^0.2.9 - version: 0.2.9 + specifier: ^0.2.11 + version: 0.2.11 typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 unbuild: specifier: ^2.0.0 - version: 2.0.0(sass@1.77.8)(typescript@5.5.4) + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) + wxt: + specifier: workspace:* + version: link:../wxt + + packages/unocss: + dependencies: + defu: + specifier: ^6.1.4 + version: 6.1.4 + fast-glob: + specifier: ^3.3.2 + version: 3.3.2 + devDependencies: + '@aklinker1/check': + specifier: ^1.4.5 + version: 1.4.5(typescript@5.6.2) + oxlint: + specifier: ^0.9.9 + version: 0.9.9 + publint: + specifier: ^0.2.11 + version: 0.2.11 + typescript: + specifier: ^5.6.2 + version: 5.6.2 + unbuild: + specifier: ^2.0.0 + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) + unocss: + specifier: ^0.63.3 + version: 0.63.4(postcss@8.4.47)(rollup@4.24.0)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) wxt: specifier: workspace:* version: link:../wxt @@ -296,7 +323,7 @@ importers: dependencies: '@aklinker1/rollup-plugin-visualizer': specifier: 5.12.0 - version: 5.12.0(rollup@4.19.0) + version: 5.12.0(rollup@4.24.0) '@types/chrome': specifier: ^0.0.269 version: 0.0.269 @@ -316,8 +343,8 @@ importers: specifier: ^0.5.0 version: 0.5.0 c12: - specifier: ^1.11.1 - version: 1.11.1(magicast@0.3.4) + specifier: ^1.11.2 + version: 1.11.2(magicast@0.3.5) cac: specifier: ^6.7.14 version: 6.7.14 @@ -336,18 +363,18 @@ importers: dequal: specifier: ^2.0.3 version: 2.0.3 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 esbuild: - specifier: ^0.23.0 - version: 0.23.0 - execa: - specifier: ^9.3.1 - version: 9.3.1 + specifier: ^0.21.5 + version: 0.21.5 fast-glob: specifier: ^3.3.2 version: 3.3.2 filesize: - specifier: ^10.1.4 - version: 10.1.4 + specifier: ^10.1.6 + version: 10.1.6 fs-extra: specifier: ^11.2.0 version: 11.2.0 @@ -373,53 +400,56 @@ importers: specifier: ^3.10.1 version: 3.10.1 linkedom: - specifier: ^0.18.4 - version: 0.18.4 + specifier: ^0.18.5 + version: 0.18.5 magicast: - specifier: ^0.3.4 - version: 0.3.4 + specifier: ^0.3.5 + version: 0.3.5 minimatch: specifier: ^10.0.1 version: 10.0.1 - natural-compare: - specifier: ^1.4.0 - version: 1.4.0 + nano-spawn: + specifier: ^0.1.0 + version: 0.1.0 normalize-path: specifier: ^3.0.0 version: 3.0.0 nypm: - specifier: ^0.3.9 - version: 0.3.9 + specifier: ^0.3.12 + version: 0.3.12 ohash: - specifier: ^1.1.3 - version: 1.1.3 + specifier: ^1.1.4 + version: 1.1.4 open: specifier: ^10.1.0 version: 10.1.0 ora: specifier: ^8.1.0 version: 8.1.0 + perfect-debounce: + specifier: ^1.0.0 + version: 1.0.0 picocolors: - specifier: ^1.0.1 - version: 1.0.1 + specifier: ^1.1.0 + version: 1.1.0 prompts: specifier: ^2.4.2 version: 2.4.2 publish-browser-extension: - specifier: ^2.1.3 - version: 2.1.3 + specifier: ^2.2.2 + version: 2.2.2 scule: specifier: ^1.3.0 version: 1.3.0 unimport: - specifier: ^3.11.1 - version: 3.11.1(rollup@4.19.0) + specifier: ^3.13.1 + version: 3.13.1(rollup@4.24.0)(webpack-sources@3.2.3) vite: - specifier: ^5.3.5 - version: 5.3.5(@types/node@20.14.12)(sass@1.77.8) + specifier: ^5.4.8 + version: 5.4.8(@types/node@20.16.10)(sass@1.79.4) vite-node: - specifier: ^2.0.4 - version: 2.0.4(@types/node@20.14.12)(sass@1.77.8) + specifier: ^2.1.2 + version: 2.1.2(@types/node@20.16.10)(sass@1.79.4) web-ext-run: specifier: ^0.2.1 version: 0.2.1 @@ -429,7 +459,7 @@ importers: devDependencies: '@aklinker1/check': specifier: ^1.4.5 - version: 1.4.5(typescript@5.5.4) + version: 1.4.5(typescript@5.6.2) '@faker-js/faker': specifier: ^8.4.1 version: 8.4.1 @@ -439,12 +469,9 @@ importers: '@types/lodash.merge': specifier: ^4.6.9 version: 4.6.9 - '@types/natural-compare': - specifier: ^1.4.3 - version: 1.4.3 '@types/node': - specifier: ^20.14.12 - version: 20.14.12 + specifier: ^20.16.10 + version: 20.16.10 '@types/normalize-path': specifier: ^3.0.2 version: 3.0.2 @@ -461,29 +488,26 @@ importers: specifier: ^4.6.2 version: 4.6.2 oxlint: - specifier: ^0.9.1 - version: 0.9.1 - p-map: - specifier: ^7.0.2 - version: 7.0.2 + specifier: ^0.9.9 + version: 0.9.9 publint: - specifier: ^0.2.9 - version: 0.2.9 + specifier: ^0.2.11 + version: 0.2.11 tsx: specifier: 4.15.7 version: 4.15.7 typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 unbuild: specifier: ^2.0.0 - version: 2.0.0(sass@1.77.8)(typescript@5.5.4) + version: 2.0.0(sass@1.79.4)(typescript@5.6.2) vitest: - specifier: ^2.0.4 - version: 2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8) + specifier: ^2.1.2 + version: 2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4) vitest-plugin-random-seed: specifier: ^1.1.0 - version: 1.1.0(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) + version: 1.1.0(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) packages/wxt-demo: dependencies: @@ -501,37 +525,41 @@ importers: specifier: ^0.0.269 version: 0.0.269 '@types/react': - specifier: ^18.3.3 - version: 18.3.3 + specifier: ^18.3.11 + version: 18.3.11 '@types/react-dom': specifier: ^18.3.0 version: 18.3.0 '@wxt-dev/auto-icons': specifier: workspace:* version: link:../auto-icons + '@wxt-dev/unocss': + specifier: workspace:* + version: link:../unocss sass: - specifier: ^1.77.8 - version: 1.77.8 + specifier: ^1.79.4 + version: 1.79.4 typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 + unocss: + specifier: ^0.63.3 + version: 0.63.4(postcss@8.4.47)(rollup@4.24.0)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) vitest: - specifier: ^2.0.4 - version: 2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8) + specifier: ^2.1.2 + version: 2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4) vitest-plugin-random-seed: specifier: ^1.1.0 - version: 1.1.0(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) + version: 1.1.0(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) wxt: specifier: workspace:* version: link:../wxt packages: - '@aklinker1/buildc@1.1.1': - resolution: {integrity: sha512-QuR0c0TkA/8BXh9g+MbLch7FajeBZXZWnKxIsAu4B1zVtMkKze1gvsnoiwRfyVoDjOzqO47RItc1DnCMBPHyvg==} + '@aklinker1/buildc@1.1.4': + resolution: {integrity: sha512-3SQ2zVEsX+UWg/mHfp9TqU9OPI8abRGTOadChQB0Aqb4dtIy311pBddndVPuuD4uQfIhKbvPxkzZ0rwvlw52Rw==} hasBin: true - peerDependencies: - typescript: ^5.0.0 '@aklinker1/check@1.4.5': resolution: {integrity: sha512-whVpnpSK4qa4/83q22JAmxwRAEj35qYs8eIH/tX1C6rKbiwx7EL6kQVmSAhCe1NYqzoIWyOgsISdDPyHjC+h2A==} @@ -619,6 +647,12 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@antfu/install-pkg@0.4.1': + resolution: {integrity: sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==} + + '@antfu/utils@0.7.10': + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + '@antfu/utils@0.7.7': resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==} @@ -626,22 +660,42 @@ packages: resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.25.7': + resolution: {integrity: sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.24.7': resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.25.7': + resolution: {integrity: sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==} + engines: {node: '>=6.9.0'} + '@babel/core@7.24.7': resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} engines: {node: '>=6.9.0'} + '@babel/core@7.25.7': + resolution: {integrity: sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.24.7': resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} engines: {node: '>=6.9.0'} + '@babel/generator@7.25.7': + resolution: {integrity: sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==} + engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.24.7': resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.25.7': + resolution: {integrity: sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==} + engines: {node: '>=6.9.0'} + '@babel/helper-environment-visitor@7.24.7': resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} engines: {node: '>=6.9.0'} @@ -662,12 +716,22 @@ packages: resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.25.7': + resolution: {integrity: sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-transforms@7.24.7': resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.25.7': + resolution: {integrity: sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-plugin-utils@7.24.7': resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} engines: {node: '>=6.9.0'} @@ -676,48 +740,73 @@ packages: resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} engines: {node: '>=6.9.0'} - '@babel/helper-split-export-declaration@7.24.7': - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + '@babel/helper-simple-access@7.25.7': + resolution: {integrity: sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.24.1': - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.24.7': resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.5': - resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} + '@babel/helper-string-parser@7.24.8': + resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.7': + resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==} engines: {node: '>=6.9.0'} '@babel/helper-validator-identifier@7.24.7': resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.7': + resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.24.7': resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.7': + resolution: {integrity: sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==} + engines: {node: '>=6.9.0'} + '@babel/helpers@7.24.7': resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} engines: {node: '>=6.9.0'} + '@babel/helpers@7.25.7': + resolution: {integrity: sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==} + engines: {node: '>=6.9.0'} + '@babel/highlight@7.24.7': resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.24.5': - resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} - engines: {node: '>=6.0.0'} - hasBin: true + '@babel/highlight@7.25.7': + resolution: {integrity: sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==} + engines: {node: '>=6.9.0'} '@babel/parser@7.24.7': resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.25.6': + resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@7.25.7': + resolution: {integrity: sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-syntax-jsx@7.24.7': resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} engines: {node: '>=6.9.0'} @@ -748,18 +837,30 @@ packages: resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} engines: {node: '>=6.9.0'} + '@babel/template@7.25.7': + resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.24.7': resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} engines: {node: '>=6.9.0'} - '@babel/types@7.24.5': - resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} + '@babel/traverse@7.25.7': + resolution: {integrity: sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==} engines: {node: '>=6.9.0'} '@babel/types@7.24.7': resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} engines: {node: '>=6.9.0'} + '@babel/types@7.25.6': + resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.25.7': + resolution: {integrity: sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} @@ -776,14 +877,14 @@ packages: engines: {node: '>= 0.10.4'} hasBin: true - '@docsearch/css@3.6.0': - resolution: {integrity: sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==} + '@docsearch/css@3.6.2': + resolution: {integrity: sha512-vKNZepO2j7MrYBTZIGXvlUOIR+v9KRf70FApRgovWrj3GTs1EITz/Xb0AOlm1xsQBp16clVZj1SY/qaOJbQtZw==} - '@docsearch/js@3.6.0': - resolution: {integrity: sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==} + '@docsearch/js@3.6.2': + resolution: {integrity: sha512-pS4YZF+VzUogYrkblCucQ0Oy2m8Wggk8Kk7lECmZM60hTbaydSIhJTTiCrmoxtBqV8wxORnOqcqqOfbmkkQEcA==} - '@docsearch/react@3.6.0': - resolution: {integrity: sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==} + '@docsearch/react@3.6.2': + resolution: {integrity: sha512-rtZce46OOkVflCQH71IdbXSFK+S8iJZlUF56XBW5rIgx/eG5qoomC7Ag3anZson1bBac/JFQn7XOBfved/IMRA==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' react: '>= 16.8.0 < 19.0.0' @@ -1226,6 +1327,12 @@ packages: resolution: {integrity: sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'} + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@2.1.33': + resolution: {integrity: sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==} + '@img/sharp-darwin-arm64@0.33.5': resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -1339,10 +1446,6 @@ packages: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -1376,43 +1479,43 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxlint/darwin-arm64@0.9.1': - resolution: {integrity: sha512-SzYTggt2eJqMhemijEv9AszSdc8Vv1OBQbmAZpDNPHmwlDzPKEopSrDURwt/Jq56FYsJC/jhzBzrJLXSK55i1A==} + '@oxlint/darwin-arm64@0.9.9': + resolution: {integrity: sha512-My2KfUByjRl49p0rr/Glx9Y/hjney1uFk0JXNjwHqYToHqO9fY/IZ6XT1fdw9sX+1hdpq9bmj88rnkpvu0/cRw==} cpu: [arm64] os: [darwin] - '@oxlint/darwin-x64@0.9.1': - resolution: {integrity: sha512-IDgjpNdtt2XkEcWDIhFyZCkIIonqlBQf3jQ2L1voGQxQFwjl+cP9+hdpFp/m89qGO708MULeegCH+MGq28xWbg==} + '@oxlint/darwin-x64@0.9.9': + resolution: {integrity: sha512-k0r0t+MAzrk8yWs0nxyD9Skfb+Ozmu6HRMTJIsUTLV4AKMt9CZBlLVS0OXzXHi72AOHz3UUve5rXxevVVY9lHQ==} cpu: [x64] os: [darwin] - '@oxlint/linux-arm64-gnu@0.9.1': - resolution: {integrity: sha512-kEGN/CNdUB11So4c3OpTIJi0YvPgu5i9gvUcWX+CxEkeACRPj8dq7/Rm1FgfIqky6oYY5QjXDioZ+yKt+Xw1rQ==} + '@oxlint/linux-arm64-gnu@0.9.9': + resolution: {integrity: sha512-atiotr1pN3rr0i7Ww3SpOEOvkFex97S8GwYmiTlSng0kp+FSIZD6Kjlr9k3oayf9RZUDRuAE4WptwV1KYLvIDw==} cpu: [arm64] os: [linux] - '@oxlint/linux-arm64-musl@0.9.1': - resolution: {integrity: sha512-US5UVB7JDwNuQa2+RZyWzEtgjEOA9wAvwUy8oUmgqomo02cpCrZo3wOQAvAckE5KxJCskr7T6pGW9eA8y3IhsQ==} + '@oxlint/linux-arm64-musl@0.9.9': + resolution: {integrity: sha512-vmd6Eog6WiudMTT0Fa8u5N+47caaWF2KVUHOSEV/d/WauVx+ZOR9z1LEM+54AZwn3Z2TbtFOJDiz7iDukZPbfw==} cpu: [arm64] os: [linux] - '@oxlint/linux-x64-gnu@0.9.1': - resolution: {integrity: sha512-w2Sz/WevEa6FxDjwwg9xbmpebDmLXO9YCvUUs5K4emKhzh05xEwuXrD2kJuQUdFapiHHQUMTQ5/iBF0NOPb9Uw==} + '@oxlint/linux-x64-gnu@0.9.9': + resolution: {integrity: sha512-AUmSRerK4VXIMcTYYk25KGoOU2/z+NGItUhI6nJgMFktrbF8MUD6hlf3vaQZNle454z7FDJNSjARM0bB+xpBiQ==} cpu: [x64] os: [linux] - '@oxlint/linux-x64-musl@0.9.1': - resolution: {integrity: sha512-hSukTLTn+wKyJUbR3934bOmWNoDaJv4yJwumE6QqBQZWoFNyd3seiYJLPWD+7aMJx6nOnot8uqjnvYO1QZsccA==} + '@oxlint/linux-x64-musl@0.9.9': + resolution: {integrity: sha512-jQYIx5KUYbpXbXBFPgIwRPLSm3AO5wa+32BQYASIOCPcsPywV+HJKbQpzmWqXDYel6hrifmIxspgxHhGMlHJ1Q==} cpu: [x64] os: [linux] - '@oxlint/win32-arm64@0.9.1': - resolution: {integrity: sha512-9Y7RuvnulhZyxLdsDrGRaojxytzcBTGHpl7AxED41G/IXGPOs+dE1q2NFyHWB6Gfzi/MJZ6plXYIOKx/e/3t/g==} + '@oxlint/win32-arm64@0.9.9': + resolution: {integrity: sha512-HSOztIKmiivfUAoxGx4qyerYV+aAXGvKbwWf8j4RorAEg2WWBdhVe9XHoSdqgYsOBi1515+YXxXiSRX3F/0xAg==} cpu: [arm64] os: [win32] - '@oxlint/win32-x64@0.9.1': - resolution: {integrity: sha512-51wrzMDGFyCYZbhSczU9VS7EYe1N0tNlDfdne6VCKgpPPJX0+XLZHybgUFZNYVyf7/W5t1/gpyOTFErVYRP0pw==} + '@oxlint/win32-x64@0.9.9': + resolution: {integrity: sha512-T1/tNxqoYd/MMqi1dhSVzAVL0ZINvXDBEQWm6OCSrrjRM6c9UQydTzsgLWfvm9uHWngcMuRGXhN3F+D6KEYs3w==} cpu: [x64] os: [win32] @@ -1432,6 +1535,9 @@ packages: resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} engines: {node: '>=12'} + '@polka/url@1.0.0-next.28': + resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + '@rollup/plugin-alias@5.1.0': resolution: {integrity: sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ==} engines: {node: '>=14.0.0'} @@ -1486,106 +1592,117 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.19.0': - resolution: {integrity: sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==} + '@rollup/pluginutils@5.1.2': + resolution: {integrity: sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.24.0': + resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.19.0': - resolution: {integrity: sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==} + '@rollup/rollup-android-arm64@4.24.0': + resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.19.0': - resolution: {integrity: sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==} + '@rollup/rollup-darwin-arm64@4.24.0': + resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.19.0': - resolution: {integrity: sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==} + '@rollup/rollup-darwin-x64@4.24.0': + resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.19.0': - resolution: {integrity: sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==} + '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.19.0': - resolution: {integrity: sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==} + '@rollup/rollup-linux-arm-musleabihf@4.24.0': + resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.19.0': - resolution: {integrity: sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==} + '@rollup/rollup-linux-arm64-gnu@4.24.0': + resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.19.0': - resolution: {integrity: sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==} + '@rollup/rollup-linux-arm64-musl@4.24.0': + resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.19.0': - resolution: {integrity: sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.19.0': - resolution: {integrity: sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==} + '@rollup/rollup-linux-riscv64-gnu@4.24.0': + resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.19.0': - resolution: {integrity: sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==} + '@rollup/rollup-linux-s390x-gnu@4.24.0': + resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.19.0': - resolution: {integrity: sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==} + '@rollup/rollup-linux-x64-gnu@4.24.0': + resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.19.0': - resolution: {integrity: sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==} + '@rollup/rollup-linux-x64-musl@4.24.0': + resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.19.0': - resolution: {integrity: sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==} + '@rollup/rollup-win32-arm64-msvc@4.24.0': + resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.19.0': - resolution: {integrity: sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==} + '@rollup/rollup-win32-ia32-msvc@4.24.0': + resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.19.0': - resolution: {integrity: sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==} + '@rollup/rollup-win32-x64-msvc@4.24.0': + resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} cpu: [x64] os: [win32] - '@sec-ant/readable-stream@0.4.1': - resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + '@shikijs/core@1.21.0': + resolution: {integrity: sha512-zAPMJdiGuqXpZQ+pWNezQAk5xhzRXBNiECFPcJLtUdsFM3f//G95Z15EHTnHchYycU8kIIysqGgxp8OVSj1SPQ==} - '@shikijs/core@1.10.3': - resolution: {integrity: sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==} + '@shikijs/engine-javascript@1.21.0': + resolution: {integrity: sha512-jxQHNtVP17edFW4/0vICqAVLDAxmyV31MQJL4U/Kg+heQALeKYVOWo0sMmEZ18FqBt+9UCdyqGKYE7bLRtk9mg==} - '@shikijs/transformers@1.10.3': - resolution: {integrity: sha512-MNjsyye2WHVdxfZUSr5frS97sLGe6G1T+1P41QjyBFJehZphMcr4aBlRLmq6OSPBslYe9byQPVvt/LJCOfxw8Q==} + '@shikijs/engine-oniguruma@1.21.0': + resolution: {integrity: sha512-AIZ76XocENCrtYzVU7S4GY/HL+tgHGbVU+qhiDyNw1qgCA5OSi4B4+HY4BtAoJSMGuD/L5hfTzoRVbzEm2WTvg==} - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@shikijs/transformers@1.21.0': + resolution: {integrity: sha512-aA+XGGSzipcvqdsOYL8l6Q2RYiMuJNdhdt9eZnkJmW+wjSOixN/I7dBq3fISwvEMDlawrtuXM3eybLCEC+Fjlg==} + + '@shikijs/types@1.21.0': + resolution: {integrity: sha512-tzndANDhi5DUndBtpojEq/42+dpUF2wS7wdCDQaFtIXm3Rd1QkrcVgSSRLOvEwexekihOXfbYJINW37g96tJRw==} + + '@shikijs/vscode-textmate@9.2.2': + resolution: {integrity: sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==} '@sindresorhus/is@5.4.1': resolution: {integrity: sha512-axlrvsHlHlFmKKMEg4VyvMzFr93JWJj4eIfXY1STVuO2fsImCa7ncaiG5gC8HKOX590AW5RtRsC41/B+OfrSqw==} engines: {node: '>=14.16'} - '@sindresorhus/merge-streams@4.0.0': - resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} - engines: {node: '>=18'} - '@sveltejs/vite-plugin-svelte-inspector@2.1.0': resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} engines: {node: ^18.0.0 || >=20} @@ -1594,8 +1711,8 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 - '@sveltejs/vite-plugin-svelte@3.1.1': - resolution: {integrity: sha512-rimpFEAboBBHIlzISibg94iP09k/KYdHgVhJlcsTfn7KMBhc70jFX/GRWkRdFCc2fdnk+4+Bdfej23cMDnJS6A==} + '@sveltejs/vite-plugin-svelte@3.1.2': + resolution: {integrity: sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==} engines: {node: ^18.0.0 || >=20} peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 @@ -1630,6 +1747,9 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/filesystem@0.0.36': resolution: {integrity: sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==} @@ -1660,8 +1780,11 @@ packages: '@types/lodash@4.14.200': resolution: {integrity: sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==} - '@types/markdown-it@14.1.1': - resolution: {integrity: sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==} + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} '@types/mdurl@2.0.0': resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} @@ -1669,14 +1792,11 @@ packages: '@types/minimatch@3.0.5': resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - '@types/natural-compare@1.4.3': - resolution: {integrity: sha512-XCAxy+Gg6+S6VagwzcknnvCKujj/bVv1q+GFuCrFEelqaZPqJoC+FeXLwc2dp+oLP7qDZQ4ZfQiTJQ9sIUmlLw==} - '@types/node@20.10.3': resolution: {integrity: sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==} - '@types/node@20.14.12': - resolution: {integrity: sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==} + '@types/node@20.16.10': + resolution: {integrity: sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==} '@types/normalize-path@3.0.2': resolution: {integrity: sha512-DO++toKYPaFn0Z8hQ7Tx+3iT9t77IJo/nDiqTXilgEP+kPNIYdpS9kh3fXuc53ugqwp9pxC1PVjCpV1tQDyqMA==} @@ -1690,8 +1810,8 @@ packages: '@types/react-dom@18.3.0': resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - '@types/react@18.3.3': - resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + '@types/react@18.3.11': + resolution: {integrity: sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==} '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -1711,123 +1831,197 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@vitejs/plugin-react@4.3.1': - resolution: {integrity: sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==} + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@unocss/astro@0.63.4': + resolution: {integrity: sha512-qu1uMDUT8lXU3mm5EjZpnizvjSYtfY0TTDivR5QNm1i3Xd+ErHfdfOpXdJ2mYvxv+X7C570//KUugkTI3Mb3kQ==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + vite: + optional: true + + '@unocss/cli@0.63.4': + resolution: {integrity: sha512-kBWEiVW7KWfjptAJsk38w9dVqOmrO2/z0WADFnlX2RuKNDoCn422Rus6tFB12wZsEujC9eFM34P2nnU7IWWtlQ==} + engines: {node: '>=14'} + hasBin: true + + '@unocss/config@0.63.4': + resolution: {integrity: sha512-LfAzM8z0r2comUW94KaSo4JaaEZjPkvrfyVWfO/hyaXa+/xSVIkCTW7+lfWh77hrg1e2SUY1HEvIFBg9Jvb1xQ==} + engines: {node: '>=14'} + + '@unocss/core@0.63.4': + resolution: {integrity: sha512-VB4DJ5DsRWpX64si5tWYRXf1n5UkYQqe2s1V22qFiWmXa7Ec+Vf9s3cxWZmoWFC5P9RQiwM9kAqxdg1G+elVkQ==} + + '@unocss/extractor-arbitrary-variants@0.63.4': + resolution: {integrity: sha512-gI/+2Nv+cH/ZoOc/4X7RLD9CuBXH51jfwGJ1xRveS7tj+EBs8VshP7Vhbn6Jyp69E00wt4hyzjviDoGqcIA8bA==} + + '@unocss/inspector@0.63.4': + resolution: {integrity: sha512-NHvOTScsMrh6oMmwGMrqB1q1RCFTHZCIK0Vwp8hL8/gmNlza2Kd2cQ/WYSEsjW132xeLCOqTME5qny1gpG6SpA==} + + '@unocss/postcss@0.63.4': + resolution: {integrity: sha512-JnSAV1hAZumkm0KZGXYqWsP2I7wnOdr+oeDckHKLdZR2mHNVbDm46H8XGbie55t/gPftaLSsMbaPvRjU2Fclqg==} + engines: {node: '>=14'} + peerDependencies: + postcss: ^8.4.21 + + '@unocss/preset-attributify@0.63.4': + resolution: {integrity: sha512-Q2DT4oVdxaL7XxD9sDP3adb5tnYr05sCxCxPhv3ch8brU7uvwbyqkiEw105pWbj0Hb3i/0kD4iq7lVMZYRH5nw==} + + '@unocss/preset-icons@0.63.4': + resolution: {integrity: sha512-V7JV2xvEGeNVjP6HT4IG/BY/HgajJt9CLT2sgKbaVCU9hNOuBs1YTOxua0KLynbTYwr5F5cDMuE/9slQYinZmg==} + + '@unocss/preset-mini@0.63.4': + resolution: {integrity: sha512-sim1/uy/XaVzdnMdepXdbdacXF5QNkPDnl4PYBWTyGuT5yKFpuipWpJDS5zZH5W6PYzKdcDA3YiaJ0S5CiUWpQ==} + + '@unocss/preset-tagify@0.63.4': + resolution: {integrity: sha512-RQkeSCKrGAowomjh8/chlnVWWOFlC+QkHB1oY5isRXNO2HStESZljyL/MisRpgjj0ubPiocoFCI2hRzXT/HrSg==} + + '@unocss/preset-typography@0.63.4': + resolution: {integrity: sha512-PtRXDqF8dW1GYDxiF1Opl+M5fhZeKx63bhvtXXf3iHjVzPDSHB6w1kTElh6vIWeLDNM9GZbbJyB5f2C8DBjibw==} + + '@unocss/preset-uno@0.63.4': + resolution: {integrity: sha512-VMc2R0XRMjXA5u5HnP0SkiWtc8EnEJvipNPKsWBuyyVb0QrsIXtF5z3l3cuZmD6V7m/o9s81yshL0gFOBpF7iQ==} + + '@unocss/preset-web-fonts@0.63.4': + resolution: {integrity: sha512-XuU4dNwTQ0ULlYpQFSKk2JRYACTzpIzpPGP5ZnqdwBxEQH5JhXx4mEmaOhu1OH3c2hZURAkdQvBzYWia4oZ6og==} + + '@unocss/preset-wind@0.63.4': + resolution: {integrity: sha512-8fTUp6ZxH9YiScz4nZ1tRqprayrlQSfguzkjxDvOrwazfNcmxvHSZfC9dtpEmY+QssM1zHH0mmWmWgQYwU9Zdw==} + + '@unocss/reset@0.63.4': + resolution: {integrity: sha512-7lnVH9zuVMekY0IUtcQRrbEqlkhvyGixgzHSWPBF/JA/Pto18bhd+cMeZhuz4eHRbN274bANX+//I+Ilfo7SSg==} + + '@unocss/rule-utils@0.63.4': + resolution: {integrity: sha512-7yRWF881ymxnMcCJSiI/1kMI8uwRqRi3l5XnV+JSGjjF2fDr1POUQjSLaA4s7ZfdEgmjagdLK3F5xqkfMMECNA==} + engines: {node: '>=14'} + + '@unocss/transformer-attributify-jsx@0.63.4': + resolution: {integrity: sha512-5cO9BY/Bga6YmbTch1Neg+E46HerJp5wLxPkIcFCDNsqy2MsB97jsFG1dO0jDUg43E26MRI19tg1eqrWL6sTYg==} + + '@unocss/transformer-compile-class@0.63.4': + resolution: {integrity: sha512-ta6mqq2S5OWcfBzzYnaiMt3ekn2ECNZTqzzqMglnIKPkE+GmqUmmRavRnpc+NGobuqMRcI4F6x8MSSHf4MV0jw==} + + '@unocss/transformer-directives@0.63.4': + resolution: {integrity: sha512-N/dNhmn3e9/Z4IvAujxCdwhNMfx2SihPA2/7GFSMMRi7F0Hn/o2hOqQquRqIJbQwIvi6bJtKwyasxjDoUhJqBA==} + + '@unocss/transformer-variant-group@0.63.4': + resolution: {integrity: sha512-uEHltdfR0Y1nvs1eqHwsgevRFhZkLmA/MsaMEfNblDJ6CLHe/ACNmMoLX1Mcuq/lAPs0X6jGnKudk4QTrCv15Q==} + + '@unocss/vite@0.63.4': + resolution: {integrity: sha512-YK0L177GD8Kx+JtfiCJy4YyBYckAXo4ogC8LZ+pYVNXDMN+F+XItpGI/ofLRaGIaewNg+MJgGY+CQZceABEAfg==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + + '@vitejs/plugin-react@4.3.2': + resolution: {integrity: sha512-hieu+o05v4glEBucTcKMK3dlES0OeJlD9YVOAPraVMOInBCwzumaIFiUjr4bHK7NPgnAHgiskUoceKercrN8vg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 - '@vitejs/plugin-vue@5.0.5': - resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==} + '@vitejs/plugin-vue@5.1.4': + resolution: {integrity: sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: vite: ^5.0.0 vue: ^3.2.25 - '@vitejs/plugin-vue@5.1.1': - resolution: {integrity: sha512-sDckXxlHpMsjRQbAH9WanangrfrblsOd3pNifePs+FOHjJg1jfWq5L/P0PsBRndEt3nmdUnmvieP8ULDeX5AvA==} - engines: {node: ^18.0.0 || >=20.0.0} + '@vitest/coverage-v8@2.1.2': + resolution: {integrity: sha512-b7kHrFrs2urS0cOk5N10lttI8UdJ/yP3nB4JYTREvR5o18cR99yPpK4gK8oQgI42BVv0ILWYUSYB7AXkAUDc0g==} peerDependencies: + '@vitest/browser': 2.1.2 + vitest: 2.1.2 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@2.1.2': + resolution: {integrity: sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg==} + + '@vitest/mocker@2.1.2': + resolution: {integrity: sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA==} + peerDependencies: + '@vitest/spy': 2.1.2 + msw: ^2.3.5 vite: ^5.0.0 - vue: ^3.2.25 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true - '@vitest/coverage-v8@2.0.4': - resolution: {integrity: sha512-i4lx/Wpg5zF1h2op7j0wdwuEQxaL/YTwwQaKuKMHYj7MMh8c7I4W7PNfOptZBCSBZI0z1qwn64o0pM/pA8Tz1g==} + '@vitest/pretty-format@2.1.2': + resolution: {integrity: sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA==} + + '@vitest/runner@2.1.2': + resolution: {integrity: sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw==} + + '@vitest/snapshot@2.1.2': + resolution: {integrity: sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA==} + + '@vitest/spy@2.1.2': + resolution: {integrity: sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A==} + + '@vitest/utils@2.1.2': + resolution: {integrity: sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==} + + '@vue/compiler-core@3.5.11': + resolution: {integrity: sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==} + + '@vue/compiler-dom@3.5.11': + resolution: {integrity: sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==} + + '@vue/compiler-sfc@3.5.11': + resolution: {integrity: sha512-gsbBtT4N9ANXXepprle+X9YLg2htQk1sqH/qGJ/EApl+dgpUBdTv3yP7YlR535uHZY3n6XaR0/bKo0BgwwDniw==} + + '@vue/compiler-ssr@3.5.11': + resolution: {integrity: sha512-P4+GPjOuC2aFTk1Z4WANvEhyOykcvEd5bIj2KVNGKGfM745LaXGr++5njpdBTzVz5pZifdlR1kpYSJJpIlSePA==} + + '@vue/devtools-api@7.4.6': + resolution: {integrity: sha512-XipBV5k0/IfTr0sNBDTg7OBUCp51cYMMXyPxLXJZ4K/wmUeMqt8cVdr2ZZGOFq+si/jTyCYnNxeKoyev5DOUUA==} + + '@vue/devtools-kit@7.4.6': + resolution: {integrity: sha512-NbYBwPWgEic1AOd9bWExz9weBzFdjiIfov0yRn4DrRfR+EQJCI9dn4I0XS7IxYGdkmUJi8mFW42LLk18WsGqew==} + + '@vue/devtools-shared@7.4.6': + resolution: {integrity: sha512-rPeSBzElnHYMB05Cc056BQiJpgocQjY8XVulgni+O9a9Gr9tNXgPteSzFFD+fT/iWMxNuUgGKs9CuW5DZewfIg==} + + '@vue/reactivity@3.5.11': + resolution: {integrity: sha512-Nqo5VZEn8MJWlCce8XoyVqHZbd5P2NH+yuAaFzuNSR96I+y1cnuUiq7xfSG+kyvLSiWmaHTKP1r3OZY4mMD50w==} + + '@vue/runtime-core@3.5.11': + resolution: {integrity: sha512-7PsxFGqwfDhfhh0OcDWBG1DaIQIVOLgkwA5q6MtkPiDFjp5gohVnJEahSktwSFLq7R5PtxDKy6WKURVN1UDbzA==} + + '@vue/runtime-dom@3.5.11': + resolution: {integrity: sha512-GNghjecT6IrGf0UhuYmpgaOlN7kxzQBhxWEn08c/SQDxv1yy4IXI1bn81JgEpQ4IXjRxWtPyI8x0/7TF5rPfYQ==} + + '@vue/server-renderer@3.5.11': + resolution: {integrity: sha512-cVOwYBxR7Wb1B1FoxYvtjJD8X/9E5nlH4VSkJy2uMA1MzYNdzAAB//l8nrmN9py/4aP+3NjWukf9PZ3TeWULaA==} peerDependencies: - vitest: 2.0.4 + vue: 3.5.11 - '@vitest/expect@1.6.0': - resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} + '@vue/shared@3.5.11': + resolution: {integrity: sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==} - '@vitest/expect@2.0.4': - resolution: {integrity: sha512-39jr5EguIoanChvBqe34I8m1hJFI4+jxvdOpD7gslZrVQBKhh8H9eD7J/LJX4zakrw23W+dITQTDqdt43xVcJw==} + '@vueuse/core@11.1.0': + resolution: {integrity: sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==} - '@vitest/pretty-format@2.0.4': - resolution: {integrity: sha512-RYZl31STbNGqf4l2eQM1nvKPXE0NhC6Eq0suTTePc4mtMQ1Fn8qZmjV4emZdEdG2NOWGKSCrHZjmTqDCDoeFBw==} - - '@vitest/runner@1.6.0': - resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} - - '@vitest/runner@2.0.4': - resolution: {integrity: sha512-Gk+9Su/2H2zNfNdeJR124gZckd5st4YoSuhF1Rebi37qTXKnqYyFCd9KP4vl2cQHbtuVKjfEKrNJxHHCW8thbQ==} - - '@vitest/snapshot@1.6.0': - resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} - - '@vitest/snapshot@2.0.4': - resolution: {integrity: sha512-or6Mzoz/pD7xTvuJMFYEtso1vJo1S5u6zBTinfl+7smGUhqybn6VjzCDMhmTyVOFWwkCMuNjmNNxnyXPgKDoPw==} - - '@vitest/spy@1.6.0': - resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} - - '@vitest/spy@2.0.4': - resolution: {integrity: sha512-uTXU56TNoYrTohb+6CseP8IqNwlNdtPwEO0AWl+5j7NelS6x0xZZtP0bDWaLvOfUbaYwhhWp1guzXUxkC7mW7Q==} - - '@vitest/utils@1.6.0': - resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} - - '@vitest/utils@2.0.4': - resolution: {integrity: sha512-Zc75QuuoJhOBnlo99ZVUkJIuq4Oj0zAkrQ2VzCqNCx6wAwViHEh5Fnp4fiJTE9rA+sAoXRf00Z9xGgfEzV6fzQ==} - - '@vue/compiler-core@3.4.34': - resolution: {integrity: sha512-Z0izUf32+wAnQewjHu+pQf1yw00EGOmevl1kE+ljjjMe7oEfpQ+BI3/JNK7yMB4IrUsqLDmPecUrpj3mCP+yJQ==} - - '@vue/compiler-dom@3.4.34': - resolution: {integrity: sha512-3PUOTS1h5cskdOJMExCu2TInXuM0j60DRPpSCJDqOCupCfUZCJoyQmKtRmA8EgDNZ5kcEE7vketamRZfrEuVDw==} - - '@vue/compiler-sfc@3.4.34': - resolution: {integrity: sha512-x6lm0UrM03jjDXTPZgD9Ad8bIVD1ifWNit2EaWQIZB5CULr46+FbLQ5RpK7AXtDHGjx9rmvC7QRCTjsiGkAwRw==} - - '@vue/compiler-ssr@3.4.34': - resolution: {integrity: sha512-8TDBcLaTrFm5rnF+Qm4BlliaopJgqJ28Nsrc80qazynm5aJO+Emu7y0RWw34L8dNnTRdcVBpWzJxhGYzsoVu4g==} - - '@vue/devtools-api@7.3.6': - resolution: {integrity: sha512-z6cKyxdXrIGgA++eyGBfquj6dCplRdgjt+I18fJx8hjWTXDTIyeQvryyEBMchnfZVyvUTjK3QjGjDpLCnJxPjw==} - - '@vue/devtools-kit@7.3.6': - resolution: {integrity: sha512-5Ym9V3fkJenEoptqKoo+cgY5RTVwrSssFdzRsuyIgaeiskCT+rRJeQdwoo81tyrQ1mfS7Er1rYZlSzr3Y3L/ew==} - - '@vue/devtools-shared@7.3.6': - resolution: {integrity: sha512-R/FOmdJV+hhuwcNoxp6e87RRkEeDMVhWH+nOsnHUrwjjsyeXJ2W1475Ozmw+cbZhejWQzftkHVKO28Fuo1yqCw==} - - '@vue/reactivity@3.4.34': - resolution: {integrity: sha512-ua+Lo+wBRlBEX9TtgPOShE2JwIO7p6BTZ7t1KZVPoaBRfqbC7N3c8Mpzicx173fXxx5VXeU6ykiHo7WgLzJQDA==} - - '@vue/runtime-core@3.4.34': - resolution: {integrity: sha512-PXhkiRPwcPGJ1BnyBZFI96GfInCVskd0HPNIAZn7i3YOmLbtbTZpB7/kDTwC1W7IqdGPkTVC63IS7J2nZs4Ebg==} - - '@vue/runtime-dom@3.4.34': - resolution: {integrity: sha512-dXqIe+RqFAK2Euak4UsvbIupalrhc67OuQKpD7HJ3W2fv8jlqvI7szfBCsAEcE8o/wyNpkloxB6J8viuF/E3gw==} - - '@vue/server-renderer@3.4.34': - resolution: {integrity: sha512-GeyEUfMVRZMD/mZcNONEqg7MiU10QQ1DB3O/Qr6+8uXpbwdlmVgQ5Qs1/ZUAFX1X2UUtqMoGrDRbxdWfOJFT7Q==} - peerDependencies: - vue: 3.4.34 - - '@vue/shared@3.4.31': - resolution: {integrity: sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==} - - '@vue/shared@3.4.34': - resolution: {integrity: sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A==} - - '@vueuse/core@10.11.0': - resolution: {integrity: sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==} - - '@vueuse/integrations@10.11.0': - resolution: {integrity: sha512-Pp6MtWEIr+NDOccWd8j59Kpjy5YDXogXI61Kb1JxvSfVBO8NzFQkmrKmSZz47i+ZqHnIzxaT38L358yDHTncZg==} + '@vueuse/integrations@11.1.0': + resolution: {integrity: sha512-O2ZgrAGPy0qAjpoI2YR3egNgyEqwG85fxfwmA9BshRIGjV4G6yu6CfOPpMHAOoCD+UfsIl7Vb1bXJ6ifrHYDDA==} peerDependencies: async-validator: ^4 axios: ^1 - change-case: ^4 - drauu: ^0.3 + change-case: ^5 + drauu: ^0.4 focus-trap: ^7 - fuse.js: ^6 + fuse.js: ^7 idb-keyval: ^6 - jwt-decode: ^3 + jwt-decode: ^4 nprogress: ^0.2 qrcode: ^1.5 sortablejs: ^1 - universal-cookie: ^6 + universal-cookie: ^7 peerDependenciesMeta: async-validator: optional: true @@ -1854,11 +2048,11 @@ packages: universal-cookie: optional: true - '@vueuse/metadata@10.11.0': - resolution: {integrity: sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==} + '@vueuse/metadata@11.1.0': + resolution: {integrity: sha512-l9Q502TBTaPYGanl1G+hPgd3QX5s4CGnpXriVBR5fEZ/goI6fvDaVmIl3Td8oKFurOxTmbXvBPSsgrd6eu6HYg==} - '@vueuse/shared@10.11.0': - resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==} + '@vueuse/shared@11.1.0': + resolution: {integrity: sha512-YUtIpY122q7osj+zsNMFAfMTubGz0sn5QzE5gPzAIiCmtt2ha3uQUY1+JPyL4gRCTsLPX82Y9brNbo/aqlA91w==} '@webext-core/fake-browser@1.3.1': resolution: {integrity: sha512-NpBl0rXL6rT3msdl9Fb1GPLd/MKJEZ3pHpxuMdlu+qKW78T6SWJqDvyAVs8VjAmYs9RHoQJc+yObxQoGWdskXQ==} @@ -1869,10 +2063,6 @@ packages: '@webext-core/match-patterns@1.0.3': resolution: {integrity: sha512-NY39ACqCxdKBmHgw361M9pfJma8e4AZo20w9AY+5ZjIj1W2dvXC8J31G5fjfOGbulW9w4WKpT8fPooi0mLkn9A==} - acorn-walk@8.3.3: - resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} - engines: {node: '>=0.4.0'} - acorn@8.12.1: resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} @@ -1892,6 +2082,10 @@ packages: resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} engines: {node: '>=14.16'} + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1911,10 +2105,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} @@ -1929,9 +2119,6 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} - array-differ@4.0.0: resolution: {integrity: sha512-Q6VPTLMsmXZ47ENG3V+wQyZS1ZxXMxFyYzA+Z/GMrJ6yIutAIEf9wTyroTzmGjNfox9/h3GdGBCVh43GVFx4Uw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1940,9 +2127,6 @@ packages: resolution: {integrity: sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==} engines: {node: '>=12'} - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -1964,10 +2148,6 @@ packages: peerDependencies: postcss: ^8.1.0 - available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - axobject-query@4.0.0: resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} @@ -2030,6 +2210,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.24.0: + resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} @@ -2051,16 +2236,19 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} + bundle-require@5.0.0: + resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + bunyan@1.8.15: resolution: {integrity: sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==} engines: {'0': node >=0.10.0} hasBin: true - c12@1.10.0: - resolution: {integrity: sha512-0SsG7UDhoRWcuSvKWHaXmu5uNjDCDN3nkQLRL4Q42IlFy+ze58FcCoI3uPwINXinkz7ZinbhEgyzYFw9u9ZV8g==} - - c12@1.11.1: - resolution: {integrity: sha512-KDU0TvSvVdaYcQKQ6iPHATGz/7p/KiVjPg4vQrB6Jg/wX9R0yl5RZxWm9IoZqaIHD2+6PZd81+KMGwRr/lRIUg==} + c12@1.11.2: + resolution: {integrity: sha512-oBs8a4uvSDO9dm8b7OCFW7+dgtVrwmwnrVXYzLm43ta7ep2jCn/0MhoUFygIWtxhyy6+/MG7/agvpY0U1Iemew==} peerDependencies: magicast: ^0.3.4 peerDependenciesMeta: @@ -2079,9 +2267,6 @@ packages: resolution: {integrity: sha512-qtWGB5kn2OLjx47pYUkWicyOpK1vy9XZhq8yRTXOy+KAmjjESSRLx6SiExnnaGGUP1NM6/vmygMu0fGylNh9tw==} engines: {node: '>=14.16'} - call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} - camelcase@7.0.1: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} @@ -2092,9 +2277,11 @@ packages: caniuse-lite@1.0.30001633: resolution: {integrity: sha512-6sT0yf/z5jqf8tISAgpJDrmwOpLsrpnyCdD/lOZKvKkkJK4Dn0X5i7KF7THEZhOq+30bmhwBlNEaqPUiHiKtZg==} - chai@4.5.0: - resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} - engines: {node: '>=4'} + caniuse-lite@1.0.30001666: + resolution: {integrity: sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} chai@5.1.1: resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} @@ -2112,12 +2299,15 @@ packages: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - changelogen@0.5.5: - resolution: {integrity: sha512-IzgToIJ/R9NhVKmL+PW33ozYkv53bXvufDNUSH3GTKXq1iCHGgkbgbtqEWbo8tnWNnt7nPDpjL8PwSG2iS8RVw==} + changelogen@0.5.7: + resolution: {integrity: sha512-cTZXBcJMl3pudE40WENOakXkcVtrbBpbkmSkM20NdRiUqa4+VYRdXdEsgQ0BNQ6JBE2YymTNWtPKVF7UCTN5+g==} hasBin: true - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} @@ -2127,6 +2317,10 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} + engines: {node: '>= 14.16.0'} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -2212,6 +2406,9 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} @@ -2265,10 +2462,6 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - cross-spawn@6.0.5: - resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} - engines: {node: '>=4.8'} - cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -2294,6 +2487,10 @@ packages: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-tree@3.0.0: + resolution: {integrity: sha512-o88DVQ6GzsABn1+6+zo2ct801dBO5OASVyxbbvA2W20ue2puSh/VOuqUj90eUeMSX/xqGqBmOKiRQN7tJOuBXw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -2360,14 +2557,19 @@ packages: supports-color: optional: true + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} - deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -2411,10 +2613,6 @@ packages: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} - define-properties@1.2.0: - resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} - engines: {node: '>= 0.4'} - defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} @@ -2426,9 +2624,6 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} - destr@2.0.2: - resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==} - destr@2.0.3: resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} @@ -2436,9 +2631,8 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} @@ -2469,12 +2663,18 @@ packages: resolution: {integrity: sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==} engines: {node: '>=0.10'} + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} electron-to-chromium@1.4.802: resolution: {integrity: sha512-TnTMUATbgNdPXVSHsxvNVSG0uEd6cSZsANjm8c9HbvflZVVn1yTRcmVXYT1Ma95/ssB/Dcd30AHweH2TE+dNpA==} + electron-to-chromium@1.5.32: + resolution: {integrity: sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==} + emoji-regex@10.3.0: resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} @@ -2491,21 +2691,13 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.21.2: - resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} - engines: {node: '>= 0.4'} - - es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} @@ -2532,6 +2724,10 @@ packages: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-goat@4.0.0: resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} engines: {node: '>=12'} @@ -2569,10 +2765,6 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - execa@9.3.1: - resolution: {integrity: sha512-gdhefCCNy/8tpH/2+ajP9IQc14vXchNdd0weyzSJEFURhRMGncQ+zKFxwjAufIewPEJm9BPOaJnvg2UtlH2gPQ==} - engines: {node: ^18.19.0 || >=20.5.0} - extract-zip@2.0.1: resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -2588,12 +2780,16 @@ packages: fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - figures@6.1.0: - resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} - engines: {node: '>=18'} + fdir@6.4.2: + resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true - filesize@10.1.4: - resolution: {integrity: sha512-ryBwPIIeErmxgPnm6cbESAzXjuEFubs+yKYLBZvg3CaiNcmkJChoOGcBSrZ6IwkMwPABwPpVXE6IlNdGJJrvEg==} + filesize@10.1.6: + resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} engines: {node: '>= 10.4.0'} fill-range@7.1.1: @@ -2604,16 +2800,9 @@ packages: resolution: {integrity: sha512-I9rAm1w8U3CdhgO4EzTJsCvgcbvynZn9lOySkZf78wUdUIQH2w9QOKf3pAX+THt2XMSSR3kJSuM8P7bYux9j8g==} hasBin: true - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - focus-trap@7.5.4: resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==} - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - foreground-child@3.2.1: resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} engines: {node: '>=14'} @@ -2652,13 +2841,6 @@ packages: function-bind@1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - function.prototype.name@1.1.5: - resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} - engines: {node: '>= 0.4'} - - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - fx-runner@1.4.0: resolution: {integrity: sha512-rci1g6U0rdTg6bAaBboP7XdRu01dzTAaKXxFf+PUqGuCv6Xu7o8NZdY1D5MvKGIjb6EdS1g3VlXOgksir1uGkg==} hasBin: true @@ -2678,9 +2860,6 @@ packages: get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - get-intrinsic@1.2.1: - resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} - get-port@7.1.0: resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} engines: {node: '>=16'} @@ -2697,14 +2876,6 @@ packages: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} - get-stream@9.0.1: - resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} - engines: {node: '>=18'} - - get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} - get-tsconfig@4.7.5: resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} @@ -2740,17 +2911,10 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - globby@13.2.2: resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - got@12.6.1: resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} engines: {node: '>=14.16'} @@ -2767,13 +2931,14 @@ packages: growly@1.3.0: resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + happy-dom@14.12.3: resolution: {integrity: sha512-vsYlEs3E9gLwA1Hp+w3qzu+RUDFf4VTT8cyKqVICoZ2k7WM++Qyd2LwzyTi5bqMJFiIC/vNpTDYuxdreENRK/g==} engines: {node: '>=16.0.0'} - has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -2782,21 +2947,6 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} - - has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - has-yarn@3.0.0: resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2805,9 +2955,11 @@ packages: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} - hasha@6.0.0: - resolution: {integrity: sha512-MLydoyGp9QJcjlhE5lsLHXYpWayjjWqkavzju2ZWD2tYa1CgmML1K1gWAu22BLFa2eZ0OfvJ/DlfoVjaD54U2Q==} - engines: {node: '>=18'} + hast-util-to-html@9.0.3: + resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} highlight.js@10.7.3: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} @@ -2815,9 +2967,6 @@ packages: hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} - hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} @@ -2827,6 +2976,9 @@ packages: html-escaper@3.0.3: resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + htmlparser2@9.1.0: resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} @@ -2849,10 +3001,6 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - human-signals@8.0.0: - resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==} - engines: {node: '>=18.18.0'} - ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2874,6 +3022,9 @@ packages: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} engines: {node: '>=8'} + importx@0.4.4: + resolution: {integrity: sha512-Lo1pukzAREqrBnnHC+tj+lreMTAvyxtkKsMxLY8H15M/bvLl54p3YuoTI70Tz7Il0AsgSlD7Lrk/FaApRcBL7w==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -2892,42 +3043,24 @@ packages: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} - internal-slot@1.0.5: - resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} - engines: {node: '>= 0.4'} - is-absolute@0.1.7: resolution: {integrity: sha512-Xi9/ZSn4NFapG8RP98iNPMOeaV3mXPisxKxzKtHVqr3g56j/fBn+yZmnxSVAA8lmZbl2J9b/a4kJvfU3hqQYgA==} engines: {node: '>=0.10.0'} - is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - is-builtin-module@3.2.1: resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - is-ci@3.0.1: resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true @@ -2935,10 +3068,6 @@ packages: is-core-module@2.12.1: resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} - is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -2985,18 +3114,10 @@ packages: is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - is-npm@6.0.0: resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -3009,10 +3130,6 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} - is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - is-plain-object@2.0.4: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} @@ -3030,17 +3147,10 @@ packages: is-reference@3.0.2: resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} - is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - is-relative@0.1.3: resolution: {integrity: sha512-wBOr+rNM4gkAZqoLRJI4myw5WzzIdQosFAAbnvfXP5z1LyzgAI3ivOKehC5KfqlQJZoihVhirgtCBj378Eg8GA==} engines: {node: '>=0.10.0'} - is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -3049,22 +3159,6 @@ packages: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-stream@4.0.1: - resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} - engines: {node: '>=18'} - - is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - - is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.10: - resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} - engines: {node: '>= 0.4'} - is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} @@ -3076,9 +3170,6 @@ packages: resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} engines: {node: '>=18'} - is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - is-what@4.1.16: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} @@ -3131,6 +3222,10 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + jiti@2.0.0-beta.3: + resolution: {integrity: sha512-pmfRbVRs/7khFrSAYnSiJ8C0D5GvzkE4Ey2pAvUcJsw1ly/p+7ut27jbJrjY79BpAJQJ4gXYFtK6d1Aub+9baQ==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3142,12 +3237,14 @@ packages: engines: {node: '>=4'} hasBin: true + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-better-errors@1.0.2: - resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} - json-parse-even-better-errors@3.0.0: resolution: {integrity: sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -3177,6 +3274,9 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + latest-version@7.0.0: resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} engines: {node: '>=14.16'} @@ -3195,25 +3295,25 @@ packages: resolution: {integrity: sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - linkedom@0.18.4: - resolution: {integrity: sha512-JhLErxMIEOKByMi3fURXgI1fYOzR87L1Cn0+MI9GlMckFrqFZpV1SUGox1jcKtsKN3y6JgclcQf0FzZT//BuGw==} + linkedom@0.18.5: + resolution: {integrity: sha512-JGLaGGtqtu+eOhYrC1wkWYTBcpVWL4AsnwAtMtgO1Q0gI0PuPJKI0zBBE+a/1BrhOE3Uw8JI/ycByAv5cLrAuQ==} - lint-staged@15.2.7: - resolution: {integrity: sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==} + lint-staged@15.2.10: + resolution: {integrity: sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==} engines: {node: '>=18.12.0'} hasBin: true - listr2@8.0.2: - resolution: {integrity: sha512-v5jEMOeEJUpRjSXSB4U3w5A3YPmURYMUO/86f1PA4GGYcdbUQYpkbvKYT7Xaq1iu4Zjn51Rv1UeD1zsBXRijiQ==} - engines: {node: '>=18.0.0'} - listr2@8.2.1: resolution: {integrity: sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==} engines: {node: '>=18.0.0'} - load-json-file@4.0.0: - resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} - engines: {node: '>=4'} + listr2@8.2.5: + resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} + engines: {node: '>=18.0.0'} + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} local-pkg@0.5.0: resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} @@ -3252,13 +3352,14 @@ packages: resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} engines: {node: '>=18'} + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - loupe@3.1.1: resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} @@ -3272,10 +3373,6 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} @@ -3285,8 +3382,8 @@ packages: magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} - magicast@0.3.4: - resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==} + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -3298,6 +3395,9 @@ packages: mark.js@8.11.1: resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + markdown-it-footnote@4.0.0: + resolution: {integrity: sha512-WYJ7urf+khJYl3DqofQpYfEYkZKbmXmwxQV8c8mO/hGIhgZ1wOe7R4HLFNwqx7TjILbnC98fuyeSsin19JdFcQ==} + marked@4.3.0: resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} engines: {node: '>= 12'} @@ -3306,15 +3406,17 @@ packages: marky@1.2.5: resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + mdn-data@2.0.28: resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} + mdn-data@2.10.0: + resolution: {integrity: sha512-qq7C3EtK3yJXMwz1zAab65pjl+UhohqMOctTgcqjLOWABqmwj+me02LSsCuEUxnst9X1lCBpoE0WArGKgdGDzw==} merge-anything@5.1.7: resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} @@ -3327,12 +3429,27 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + micromark-util-character@2.1.0: + resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + + micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + + micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + + micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + + micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} - micromatch@4.0.7: - resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} mimic-fn@2.1.0: @@ -3389,8 +3506,8 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - minisearch@7.0.2: - resolution: {integrity: sha512-Pf0sFXaCgRpOBDr4G8wTbVAEH9o9rvJzCMwj0TMe3L/NfUuG188xabfx6Vm3vD/Dv5L500n7JeiMB9Mq3sWMfQ==} + minisearch@7.1.0: + resolution: {integrity: sha512-tv7c/uefWdEhcu6hvrfTihflgeEi2tN6VV7HJnCjK6VxM75QQJh4t9FwJCsA2EsRS8LCnu3W87CuGPWMocOLCA==} minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} @@ -3438,12 +3555,19 @@ packages: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + multimatch@6.0.0: resolution: {integrity: sha512-I7tSVxHGPlmPN/enE3mS1aOSo6bWBfls+3HmuEeCUBCE7gWnm3cBXCBkpurzFjVRwC6Kld8lLaZ1Iv5vOcjvcQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3458,21 +3582,19 @@ packages: nan@2.17.0: resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==} + nano-spawn@0.1.0: + resolution: {integrity: sha512-Q0fYRut0GGSoysqrS6hF1jlQEc3yOglnGXwsS+DcoaLwu6NCkUxOB8om08hvUF0V+bNRjExzKM3v8ATbfrLWyQ==} + engines: {node: '>=18.19'} + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - ncp@2.0.0: resolution: {integrity: sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==} hasBin: true - nice-try@1.0.5: - resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} - node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} @@ -3486,8 +3608,8 @@ packages: node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} @@ -3514,11 +3636,6 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} hasBin: true - npm-run-all@4.1.5: - resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==} - engines: {node: '>= 4'} - hasBin: true - npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -3530,8 +3647,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nypm@0.3.9: - resolution: {integrity: sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==} + nypm@0.3.12: + resolution: {integrity: sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA==} engines: {node: ^14.16.0 || >=16.10.0} hasBin: true @@ -3539,22 +3656,11 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + ofetch@1.4.0: + resolution: {integrity: sha512-MuHgsEhU6zGeX+EMh+8mSMrYTnsqJQQrpM00Q6QHMKNqQ0bKy0B43tk8tL1wg+CnsSTy1kg4Ir2T5Ig6rD+dfQ==} - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} - - ofetch@1.3.3: - resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==} - - ohash@1.1.3: - resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} + ohash@1.1.4: + resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -3571,6 +3677,9 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} + oniguruma-to-js@0.4.3: + resolution: {integrity: sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==} + open@10.1.0: resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} engines: {node: '>=18'} @@ -3595,8 +3704,8 @@ packages: resolution: {integrity: sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==} engines: {node: '>= 0.4.0'} - oxlint@0.9.1: - resolution: {integrity: sha512-77v9YVkaVOWguxUttiJ31yfWkG/Yo7kIzY0CrKHxM6p0xiUqN0LVF4IVgjcE6vevyd9bBVphtOgJOJUq4To/+w==} + oxlint@0.9.9: + resolution: {integrity: sha512-EqUmSKgnU7KNCi29uFe5MQnUZ0GH569Inkry/e84k4lwVRv1QuDr4DHLpu0cXBN2atwhKf1Szk/3uxmB2qgPbw==} engines: {node: '>=14.*'} hasBin: true @@ -3604,14 +3713,6 @@ packages: resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} engines: {node: '>=12.20'} - p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} - - p-map@7.0.2: - resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==} - engines: {node: '>=18'} - package-json-from-dist@1.0.0: resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} @@ -3619,21 +3720,16 @@ packages: resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} engines: {node: '>=14.16'} + package-manager-detector@0.2.2: + resolution: {integrity: sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==} + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - parse-json@4.0.0: - resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} - engines: {node: '>=4'} - parse-json@7.1.1: resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==} engines: {node: '>=16'} - parse-ms@4.0.0: - resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} - engines: {node: '>=18'} - parse5-htmlparser2-tree-adapter@6.0.1: resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} @@ -3647,10 +3743,6 @@ packages: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - path-key@2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} - engines: {node: '>=4'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -3666,10 +3758,6 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - path-type@3.0.0: - resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} - engines: {node: '>=4'} - path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -3677,9 +3765,6 @@ packages: pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - pathval@2.0.0: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} engines: {node: '>= 14.16'} @@ -3693,33 +3778,22 @@ packages: periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - pidtree@0.3.1: - resolution: {integrity: sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==} - engines: {node: '>=0.10'} - hasBin: true + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} hasBin: true - pify@3.0.0: - resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} - engines: {node: '>=4'} - - pkg-types@1.0.3: - resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} - - pkg-types@1.1.1: - resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} - pkg-types@1.1.3: resolution: {integrity: sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==} @@ -3905,6 +3979,10 @@ packages: resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + engines: {node: ^10 || ^12 || >=14} + preact@10.18.1: resolution: {integrity: sha512-mKUD7RRkQQM6s7Rkmi7IFkoEHjuFqRQUaXamO61E6Nn7vqF/bo7EZCmSyrUnp2UWHw0O7XjZ2eeXis+m7tf4lg==} @@ -3917,14 +3995,6 @@ packages: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} engines: {node: ^14.13.1 || >=16.0.0} - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - pretty-ms@9.0.0: - resolution: {integrity: sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==} - engines: {node: '>=18'} - process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -3939,16 +4009,19 @@ packages: proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + property-information@6.5.0: + resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - publint@0.2.9: - resolution: {integrity: sha512-nITKS1NSwD68PQlts0ntryhxrWObep6P0CCycwi1lgXI+K7uKyacMYRRCQi7hTae8imkI3FCi0FlgnwLxjM8yA==} + publint@0.2.11: + resolution: {integrity: sha512-/kxbd+sD/uEG515N/ZYpC6gYs8h89cQ4UIsAq1y6VT4qlNh8xmiSwcP2xU2MbzXFl8J0l2IdONKFweLfYoqhcA==} engines: {node: '>=16'} hasBin: true - publish-browser-extension@2.1.3: - resolution: {integrity: sha512-qisnXUUwjvu5kMvObfG7UQ9rPU3t0XfbKdCdCrwAXaLUySdC25nlM4gxi+CBvL7LiwvK494GJyEK/weQBhIyTQ==} + publish-browser-extension@2.2.2: + resolution: {integrity: sha512-+Kr6/S+X51PL6FhMg36yAiFxOFO9O+YQQRVNRD1ItG64Nt+QVmhSKUGJbyLrCwsS4lI0e6kqhxV8r9cy8sAWDQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -3966,9 +4039,6 @@ packages: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} - rc9@2.1.1: - resolution: {integrity: sha512-lNeOl38Ws0eNxpO3+wD1I9rkHGQyj1NU1jlzv4go2CtEnEQEUfqnIvZG7W+bC/aXdJ27n5x/yUjb6RoT9tko+Q==} - rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} @@ -3981,9 +4051,6 @@ packages: peerDependencies: react: ^18.3.1 - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} @@ -3992,10 +4059,6 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} - read-pkg@3.0.0: - resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} - engines: {node: '>=4'} - readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -4007,12 +4070,15 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + regenerator-runtime@0.14.0: resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} - regexp.prototype.flags@1.5.0: - resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} - engines: {node: '>= 0.4'} + regex@4.3.3: + resolution: {integrity: sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==} registry-auth-token@5.0.2: resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} @@ -4056,9 +4122,6 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.3.1: - resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} @@ -4079,8 +4142,8 @@ packages: engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true - rollup@4.19.0: - resolution: {integrity: sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==} + rollup@4.24.0: + resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -4105,11 +4168,8 @@ packages: safe-json-stringify@1.2.0: resolution: {integrity: sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==} - safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} - - sass@1.77.8: - resolution: {integrity: sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==} + sass@1.79.4: + resolution: {integrity: sha512-K0QDSNPXgyqO4GZq2HO5Q70TLxTH6cIT59RdoCHMivrC8rqzaTw5ab9prjz9KUN1El4FLXrBXJhik61JR4HcGg==} engines: {node: '>=14.0.0'} hasBin: true @@ -4129,19 +4189,10 @@ packages: resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} engines: {node: '>=12'} - semver@5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - semver@7.6.2: resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} @@ -4173,18 +4224,10 @@ packages: resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} - shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} @@ -4192,20 +4235,14 @@ packages: shell-quote@1.7.3: resolution: {integrity: sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==} - shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - shellwords@0.1.1: resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} shiki@0.14.5: resolution: {integrity: sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==} - shiki@1.10.3: - resolution: {integrity: sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==} - - side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + shiki@1.21.0: + resolution: {integrity: sha512-apCH5BoWTrmHDPGgg3RF8+HAAbEL/CdbYr8rMw7eIrdhCkZHdVGat5mMNlRtd1erNG01VPMIKHNQ0Pj2HMAiog==} siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -4224,6 +4261,10 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -4239,8 +4280,8 @@ packages: resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} engines: {node: '>=18'} - solid-js@1.8.19: - resolution: {integrity: sha512-h8z/TvTQYsf894LM9Iau/ZW2iAKrCzAWDwjPhMcXnonmW1OIIihc28wp82b1wwei1p81fH5+gnfNOe8RzLbDRQ==} + solid-js@1.9.1: + resolution: {integrity: sha512-Gd6QWRFfO2XKKZqVK4YwbhWZkr0jWw1dYHOt+VYebomeyikGP0SuMflf42XcDuU9HAEYDArFJIYsBNjlE7iZsw==} solid-refresh@0.6.3: resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} @@ -4251,6 +4292,10 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -4262,21 +4307,12 @@ packages: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + spawn-sync@1.0.15: resolution: {integrity: sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==} - spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - - spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - - spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - - spdx-license-ids@3.0.13: - resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} - speakingurl@14.0.1: resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} engines: {node: '>=0.10.0'} @@ -4287,9 +4323,6 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@3.6.0: - resolution: {integrity: sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==} - std-env@3.7.0: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} @@ -4317,23 +4350,12 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string.prototype.padend@3.1.4: - resolution: {integrity: sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==} - engines: {node: '>= 0.4'} - - string.prototype.trim@1.2.7: - resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.6: - resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} - - string.prototype.trimstart@1.0.6: - resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} - string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -4342,10 +4364,6 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - strip-bom@5.0.0: resolution: {integrity: sha512-p+byADHF7SzEcVnLvc/r3uognM1hUhObuHXxJcgLCfD194XAkaLbjq3Wzb0N5G2tgIjH0dgT708Z51QxMeu60A==} engines: {node: '>=12'} @@ -4358,10 +4376,6 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} - strip-final-newline@4.0.0: - resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} - engines: {node: '>=18'} - strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -4431,12 +4445,15 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tinybench@2.8.0: - resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinypool@0.8.4: - resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} - engines: {node: '>=14.0.0'} + tinyexec@0.3.0: + resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==} + + tinyglobby@0.2.9: + resolution: {integrity: sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==} + engines: {node: '>=12.0.0'} tinypool@1.0.0: resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==} @@ -4446,10 +4463,6 @@ packages: resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} engines: {node: '>=14.0.0'} - tinyspy@2.2.1: - resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} - engines: {node: '>=14.0.0'} - tinyspy@3.0.0: resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==} engines: {node: '>=14.0.0'} @@ -4470,6 +4483,13 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + ts-essentials@10.0.1: resolution: {integrity: sha512-HPH+H2bkkO8FkMDau+hFvv7KYozzned9Zr1Urn7rRPXMF4mZmCKOq+u4AI1AAW+2bofIOXTuSdKo9drQuni2dQ==} peerDependencies: @@ -4486,9 +4506,10 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - type-detect@4.1.0: - resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} - engines: {node: '>=4'} + tsx@4.19.1: + resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==} + engines: {node: '>=18.0.0'} + hasBin: true type-fest@1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} @@ -4502,13 +4523,6 @@ packages: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} engines: {node: '>=14.16'} - type-fest@4.20.0: - resolution: {integrity: sha512-MBh+PHUHHisjXf4tlx0CFWoMdjx8zCMLJHOjnV1prABYZFHqtFOyauCIK2/7w4oIfwkF8iNhLtnJEfVY2vn3iw==} - engines: {node: '>=16'} - - typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} - typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} @@ -4532,8 +4546,8 @@ packages: peerDependencies: typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x - typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} engines: {node: '>=14.17'} hasBin: true @@ -4541,18 +4555,15 @@ packages: resolution: {integrity: sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==} hasBin: true - ufo@1.4.0: - resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==} - ufo@1.5.3: resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + uhyphen@0.2.0: resolution: {integrity: sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==} - unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - unbuild@2.0.0: resolution: {integrity: sha512-JWCUYx3Oxdzvw2J9kTAp+DKE8df/BnH/JTSj6JyA4SH40ECdFu7FoJJcrm8G92B7TjofQ6GZGjJs50TRxoH6Wg==} hasBin: true @@ -4562,16 +4573,37 @@ packages: typescript: optional: true + unconfig@0.5.5: + resolution: {integrity: sha512-VQZ5PT9HDX+qag0XdgQi8tJepPhXiR/yVOkn707gJDKo31lGjRilPREiQJ9Z6zd/Ugpv6ZvO5VxVIcatldYcNQ==} + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - unimport@3.11.1: - resolution: {integrity: sha512-DuB1Uoq01LrrXTScxnwOoMSlTXxyKcULguFxbLrMDFcE/CO0ZWHpEiyhovN0mycPt7K6luAHe8laqvwvuoeUPg==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + unimport@3.13.1: + resolution: {integrity: sha512-nNrVzcs93yrZQOW77qnyOVHtb68LegvhYFwxFMfuuWScmwQmyVCG/NBuN8tYsaGzgQUVYv34E/af+Cc9u4og4A==} unique-string@3.0.0: resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} engines: {node: '>=12'} + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + universalify@1.0.0: resolution: {integrity: sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==} engines: {node: '>= 10.0.0'} @@ -4580,9 +4612,26 @@ packages: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} - unplugin@1.12.3: - resolution: {integrity: sha512-my8DH0/T/Kx33KO+6QXAqdeMYgyy0GktlOpdQjpagfHKw5DrD0ctPr7SHUyOT3g4ZVpzCQGt/qcpuoKJ/pniHA==} + unocss@0.63.4: + resolution: {integrity: sha512-MQ/ktuJ2MoXBsd117DEONFubJRQN6Og4mQJLbT+0nna2aTW4jYJESJ479mJYWq/ajonxEaM+zrf8M92VIWxzEw==} + engines: {node: '>=14'} + peerDependencies: + '@unocss/webpack': 0.63.4 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + '@unocss/webpack': + optional: true + vite: + optional: true + + unplugin@1.14.1: + resolution: {integrity: sha512-lBlHbfSFPToDYp9pjXlUEFVxYLaue9f9T1HC+4OHlmj+HnMDdz9oZY+erXfoCe/5V/7gKUSY2jpXPb9S7f0f/w==} engines: {node: '>=14.0.0'} + peerDependencies: + webpack-sources: ^3 + peerDependenciesMeta: + webpack-sources: + optional: true untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} @@ -4598,6 +4647,12 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + update-notifier@6.0.2: resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} engines: {node: '>=14.16'} @@ -4612,16 +4667,14 @@ packages: validate-html-nesting@1.2.2: resolution: {integrity: sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==} - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} - vite-node@1.6.0: - resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite-node@2.0.4: - resolution: {integrity: sha512-ZpJVkxcakYtig5iakNeL7N3trufe3M6vGuzYAr4GsbCTwobDeyPJpE4cjDhhPluv8OvQCFzu2LWp6GkoKRITXA==} + vite-node@2.1.2: + resolution: {integrity: sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -4635,8 +4688,8 @@ packages: '@testing-library/jest-dom': optional: true - vite@5.3.5: - resolution: {integrity: sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==} + vite@5.4.8: + resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -4644,6 +4697,7 @@ packages: less: '*' lightningcss: ^1.21.0 sass: '*' + sass-embedded: '*' stylus: '*' sugarss: '*' terser: ^5.4.0 @@ -4656,6 +4710,8 @@ packages: optional: true sass: optional: true + sass-embedded: + optional: true stylus: optional: true sugarss: @@ -4671,8 +4727,8 @@ packages: vite: optional: true - vitepress@1.3.1: - resolution: {integrity: sha512-soZDpg2rRVJNIM/IYMNDPPr+zTHDA5RbLDHAxacRu+Q9iZ2GwSR0QSUlLs+aEZTkG0SOX1dc8RmUYwyuxK8dfQ==} + vitepress@1.3.4: + resolution: {integrity: sha512-I1/F6OW1xl3kW4PaIMC6snxjWgf3qfziq2aqsDoFc/Gt41WbcRv++z8zjw8qGRIJ+I4bUW7ZcKFDHHN/jkH9DQ==} hasBin: true peerDependencies: markdown-it-mathjax3: ^4 @@ -4683,8 +4739,8 @@ packages: postcss: optional: true - vitest-mock-extended@2.0.0: - resolution: {integrity: sha512-iDV40gSKlN5RZRSfpOv5SKTdEeBvu4VMpLNNakDSHMWnUmnlfsEVGXHndWAfUD+nZBR+HDcQw7p/JO5sCWo1VQ==} + vitest-mock-extended@2.0.2: + resolution: {integrity: sha512-n3MBqVITKyclZ0n0y66hkT4UiiEYFQn9tteAnIxT0MPz1Z8nFcPUG3Cf0cZOyoPOj/cq6Ab1XFw2lM/qM5EDWQ==} peerDependencies: typescript: 3.x || 4.x || 5.x vitest: '>=2.0.0' @@ -4694,40 +4750,15 @@ packages: peerDependencies: vite: ^4.0.0 || ^5.0.0 - vitest@1.6.0: - resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} + vitest@2.1.2: + resolution: {integrity: sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.6.0 - '@vitest/ui': 1.6.0 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - vitest@2.0.4: - resolution: {integrity: sha512-luNLDpfsnxw5QSW4bISPe6tkxVvv5wn2BBs/PuDRkhXZ319doZyLOBr1sjfB5yCEpTiU7xCAdViM8TNVGPwoog==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.0.4 - '@vitest/ui': 2.0.4 + '@vitest/browser': 2.1.2 + '@vitest/ui': 2.1.2 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -4750,8 +4781,8 @@ packages: vscode-textmate@8.0.0: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} - vue-demi@0.14.8: - resolution: {integrity: sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==} + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} engines: {node: '>=12'} hasBin: true peerDependencies: @@ -4761,8 +4792,8 @@ packages: '@vue/composition-api': optional: true - vue@3.4.34: - resolution: {integrity: sha512-VZze05HWlA3ItreQ/ka7Sx7PoD0/3St8FEiSlSTVgb6l4hL+RjtP2/8g5WQBzZgyf8WG2f+g1bXzC7zggLhAJA==} + vue@3.5.11: + resolution: {integrity: sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -4801,21 +4832,10 @@ packages: when@3.7.7: resolution: {integrity: sha512-9lFZp/KHoqH6bPKjbWqa+3Dg/K/r2v0X/3/G2x4DBGchVS2QX2VXL3cZV994WQVnTM1/PD71Az25nAzryEUugw==} - which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - - which-typed-array@1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} - engines: {node: '>= 0.4'} - which@1.2.4: resolution: {integrity: sha512-zDRAqDSBudazdfM9zpiI30Fu9ve47htYXcGi3ln0wfKu2a7SmrT6F3VDoYONu//48V8Vz4TdCRNPjtvyRO3yBA==} hasBin: true - which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -4885,13 +4905,8 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yaml@2.4.5: - resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} - engines: {node: '>= 14'} - hasBin: true - - yaml@2.5.0: - resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} + yaml@2.5.1: + resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} engines: {node: '>= 14'} hasBin: true @@ -4914,50 +4929,44 @@ packages: yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} - yocto-queue@1.1.1: - resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} - engines: {node: '>=12.20'} - - yoctocolors@2.0.2: - resolution: {integrity: sha512-Ct97huExsu7cWeEjmrXlofevF8CvzUglJ4iGUet5B8xn1oumtAZBpHU4GzYuoE6PVqcZ5hghtBrSlhwHuR1Jmw==} - engines: {node: '>=18'} - zip-dir@2.0.0: resolution: {integrity: sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==} zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + snapshots: - '@aklinker1/buildc@1.1.1(typescript@5.5.4)': + '@aklinker1/buildc@1.1.4': dependencies: cac: 6.7.14 consola: 3.2.3 dependency-graph: 1.0.0 fast-glob: 3.3.2 fs-extra: 11.2.0 - ohash: 1.1.3 + ohash: 1.1.4 pathe: 1.1.2 proper-lockfile: 4.1.2 - typescript: 5.5.4 - yaml: 2.5.0 + yaml: 2.5.1 - '@aklinker1/check@1.4.5(typescript@5.5.4)': + '@aklinker1/check@1.4.5(typescript@5.6.2)': dependencies: '@antfu/utils': 0.7.7 ci-info: 4.0.0 citty: 0.1.6 - typescript: 5.5.4 + typescript: 5.6.2 - '@aklinker1/rollup-plugin-visualizer@5.12.0(rollup@4.19.0)': + '@aklinker1/rollup-plugin-visualizer@5.12.0(rollup@4.24.0)': dependencies: open: 8.4.2 picomatch: 2.3.1 source-map: 0.7.4 yargs: 17.7.2 optionalDependencies: - rollup: 4.19.0 + rollup: 4.24.0 '@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.15.0)': dependencies: @@ -5059,15 +5068,29 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + '@antfu/install-pkg@0.4.1': + dependencies: + package-manager-detector: 0.2.2 + tinyexec: 0.3.0 + + '@antfu/utils@0.7.10': {} + '@antfu/utils@0.7.7': {} '@babel/code-frame@7.24.7': dependencies: '@babel/highlight': 7.24.7 - picocolors: 1.0.1 + picocolors: 1.1.0 + + '@babel/code-frame@7.25.7': + dependencies: + '@babel/highlight': 7.25.7 + picocolors: 1.1.0 '@babel/compat-data@7.24.7': {} + '@babel/compat-data@7.25.7': {} + '@babel/core@7.24.7': dependencies: '@ampproject/remapping': 2.2.1 @@ -5088,13 +5111,40 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/core@7.25.7': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.25.7 + '@babel/generator': 7.25.7 + '@babel/helper-compilation-targets': 7.25.7 + '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.7) + '@babel/helpers': 7.25.7 + '@babel/parser': 7.25.7 + '@babel/template': 7.25.7 + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.7 + convert-source-map: 2.0.0 + debug: 4.3.5 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/generator@7.24.7': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 + '@babel/generator@7.25.7': + dependencies: + '@babel/types': 7.25.7 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.0.2 + '@babel/helper-compilation-targets@7.24.7': dependencies: '@babel/compat-data': 7.24.7 @@ -5103,27 +5153,42 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-compilation-targets@7.25.7': + dependencies: + '@babel/compat-data': 7.25.7 + '@babel/helper-validator-option': 7.25.7 + browserslist: 4.24.0 + lru-cache: 5.1.1 + semver: 6.3.1 + '@babel/helper-environment-visitor@7.24.7': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 '@babel/helper-function-name@7.24.7': dependencies: '@babel/template': 7.24.7 - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 '@babel/helper-hoist-variables@7.24.7': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 '@babel/helper-module-imports@7.18.6': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 '@babel/helper-module-imports@7.24.7': dependencies: '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.25.7': + dependencies: + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.7 transitivePeerDependencies: - supports-color @@ -5138,62 +5203,99 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.25.7(@babel/core@7.25.7)': + dependencies: + '@babel/core': 7.25.7 + '@babel/helper-module-imports': 7.25.7 + '@babel/helper-simple-access': 7.25.7 + '@babel/helper-validator-identifier': 7.25.7 + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + '@babel/helper-plugin-utils@7.24.7': {} '@babel/helper-simple-access@7.24.7': dependencies: '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-simple-access@7.25.7': + dependencies: + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.7 transitivePeerDependencies: - supports-color '@babel/helper-split-export-declaration@7.24.7': dependencies: - '@babel/types': 7.24.7 - - '@babel/helper-string-parser@7.24.1': {} + '@babel/types': 7.25.6 '@babel/helper-string-parser@7.24.7': {} - '@babel/helper-validator-identifier@7.24.5': {} + '@babel/helper-string-parser@7.24.8': {} + + '@babel/helper-string-parser@7.25.7': {} '@babel/helper-validator-identifier@7.24.7': {} + '@babel/helper-validator-identifier@7.25.7': {} + '@babel/helper-validator-option@7.24.7': {} + '@babel/helper-validator-option@7.25.7': {} + '@babel/helpers@7.24.7': dependencies: '@babel/template': 7.24.7 - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 + + '@babel/helpers@7.25.7': + dependencies: + '@babel/template': 7.25.7 + '@babel/types': 7.25.7 '@babel/highlight@7.24.7': dependencies: '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.1 + picocolors: 1.1.0 - '@babel/parser@7.24.5': + '@babel/highlight@7.25.7': dependencies: - '@babel/types': 7.24.5 + '@babel/helper-validator-identifier': 7.25.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.1.0 '@babel/parser@7.24.7': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 + + '@babel/parser@7.25.6': + dependencies: + '@babel/types': 7.25.6 + + '@babel/parser@7.25.7': + dependencies: + '@babel/types': 7.25.7 '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-react-jsx-self@7.24.7(@babel/core@7.24.7)': + '@babel/plugin-transform-react-jsx-self@7.24.7(@babel/core@7.25.7)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.25.7 '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-react-jsx-source@7.24.7(@babel/core@7.24.7)': + '@babel/plugin-transform-react-jsx-source@7.24.7(@babel/core@7.25.7)': dependencies: - '@babel/core': 7.24.7 + '@babel/core': 7.25.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/runtime@7.24.7': @@ -5205,8 +5307,14 @@ snapshots: '@babel/template@7.24.7': dependencies: '@babel/code-frame': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 + + '@babel/template@7.25.7': + dependencies: + '@babel/code-frame': 7.25.7 + '@babel/parser': 7.25.7 + '@babel/types': 7.25.7 '@babel/traverse@7.24.7': dependencies: @@ -5216,18 +5324,24 @@ snapshots: '@babel/helper-function-name': 7.24.7 '@babel/helper-hoist-variables': 7.24.7 '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 debug: 4.3.5 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.24.5': + '@babel/traverse@7.25.7': dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.24.5 - to-fast-properties: 2.0.0 + '@babel/code-frame': 7.25.7 + '@babel/generator': 7.25.7 + '@babel/parser': 7.25.7 + '@babel/template': 7.25.7 + '@babel/types': 7.25.7 + debug: 4.3.5 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color '@babel/types@7.24.7': dependencies: @@ -5235,6 +5349,18 @@ snapshots: '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 + '@babel/types@7.25.6': + dependencies: + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@babel/types@7.25.7': + dependencies: + '@babel/helper-string-parser': 7.25.7 + '@babel/helper-validator-identifier': 7.25.7 + to-fast-properties: 2.0.0 + '@bcoe/v8-coverage@0.2.3': {} '@devicefarmer/adbkit-logcat@2.1.3': {} @@ -5253,11 +5379,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@docsearch/css@3.6.0': {} + '@docsearch/css@3.6.2': {} - '@docsearch/js@3.6.0(@algolia/client-search@4.20.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.15.0)': + '@docsearch/js@3.6.2(@algolia/client-search@4.20.0)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.15.0)': dependencies: - '@docsearch/react': 3.6.0(@algolia/client-search@4.20.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.15.0) + '@docsearch/react': 3.6.2(@algolia/client-search@4.20.0)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.15.0) preact: 10.18.1 transitivePeerDependencies: - '@algolia/client-search' @@ -5266,14 +5392,14 @@ snapshots: - react-dom - search-insights - '@docsearch/react@3.6.0(@algolia/client-search@4.20.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.15.0)': + '@docsearch/react@3.6.2(@algolia/client-search@4.20.0)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.15.0)': dependencies: '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.15.0) '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0) - '@docsearch/css': 3.6.0 + '@docsearch/css': 3.6.2 algoliasearch: 4.20.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 18.3.11 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) search-insights: 2.15.0 @@ -5497,6 +5623,20 @@ snapshots: '@faker-js/faker@8.4.1': {} + '@iconify/types@2.0.0': {} + + '@iconify/utils@2.1.33': + dependencies: + '@antfu/install-pkg': 0.4.1 + '@antfu/utils': 0.7.10 + '@iconify/types': 2.0.0 + debug: 4.3.7 + kolorist: 1.8.0 + local-pkg: 0.5.0 + mlly: 1.7.1 + transitivePeerDependencies: + - supports-color + '@img/sharp-darwin-arm64@0.33.5': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.0.4 @@ -5583,10 +5723,6 @@ snapshots: '@istanbuljs/schema@0.1.3': {} - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -5618,28 +5754,28 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - '@oxlint/darwin-arm64@0.9.1': + '@oxlint/darwin-arm64@0.9.9': optional: true - '@oxlint/darwin-x64@0.9.1': + '@oxlint/darwin-x64@0.9.9': optional: true - '@oxlint/linux-arm64-gnu@0.9.1': + '@oxlint/linux-arm64-gnu@0.9.9': optional: true - '@oxlint/linux-arm64-musl@0.9.1': + '@oxlint/linux-arm64-musl@0.9.9': optional: true - '@oxlint/linux-x64-gnu@0.9.1': + '@oxlint/linux-x64-gnu@0.9.9': optional: true - '@oxlint/linux-x64-musl@0.9.1': + '@oxlint/linux-x64-musl@0.9.9': optional: true - '@oxlint/win32-arm64@0.9.1': + '@oxlint/win32-arm64@0.9.9': optional: true - '@oxlint/win32-x64@0.9.1': + '@oxlint/win32-x64@0.9.9': optional: true '@pkgjs/parseargs@0.11.0': @@ -5657,6 +5793,8 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 + '@polka/url@1.0.0-next.28': {} + '@rollup/plugin-alias@5.1.0(rollup@3.29.4)': dependencies: slash: 4.0.0 @@ -5706,98 +5844,115 @@ snapshots: optionalDependencies: rollup: 3.29.4 - '@rollup/pluginutils@5.1.0(rollup@4.19.0)': + '@rollup/pluginutils@5.1.2(rollup@4.24.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.19.0 + rollup: 4.24.0 - '@rollup/rollup-android-arm-eabi@4.19.0': + '@rollup/rollup-android-arm-eabi@4.24.0': optional: true - '@rollup/rollup-android-arm64@4.19.0': + '@rollup/rollup-android-arm64@4.24.0': optional: true - '@rollup/rollup-darwin-arm64@4.19.0': + '@rollup/rollup-darwin-arm64@4.24.0': optional: true - '@rollup/rollup-darwin-x64@4.19.0': + '@rollup/rollup-darwin-x64@4.24.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.19.0': + '@rollup/rollup-linux-arm-gnueabihf@4.24.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.19.0': + '@rollup/rollup-linux-arm-musleabihf@4.24.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.19.0': + '@rollup/rollup-linux-arm64-gnu@4.24.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.19.0': + '@rollup/rollup-linux-arm64-musl@4.24.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.19.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.19.0': + '@rollup/rollup-linux-riscv64-gnu@4.24.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.19.0': + '@rollup/rollup-linux-s390x-gnu@4.24.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.19.0': + '@rollup/rollup-linux-x64-gnu@4.24.0': optional: true - '@rollup/rollup-linux-x64-musl@4.19.0': + '@rollup/rollup-linux-x64-musl@4.24.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.19.0': + '@rollup/rollup-win32-arm64-msvc@4.24.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.19.0': + '@rollup/rollup-win32-ia32-msvc@4.24.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.19.0': + '@rollup/rollup-win32-x64-msvc@4.24.0': optional: true - '@sec-ant/readable-stream@0.4.1': {} - - '@shikijs/core@1.10.3': + '@shikijs/core@1.21.0': dependencies: + '@shikijs/engine-javascript': 1.21.0 + '@shikijs/engine-oniguruma': 1.21.0 + '@shikijs/types': 1.21.0 + '@shikijs/vscode-textmate': 9.2.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.3 + + '@shikijs/engine-javascript@1.21.0': + dependencies: + '@shikijs/types': 1.21.0 + '@shikijs/vscode-textmate': 9.2.2 + oniguruma-to-js: 0.4.3 + + '@shikijs/engine-oniguruma@1.21.0': + dependencies: + '@shikijs/types': 1.21.0 + '@shikijs/vscode-textmate': 9.2.2 + + '@shikijs/transformers@1.21.0': + dependencies: + shiki: 1.21.0 + + '@shikijs/types@1.21.0': + dependencies: + '@shikijs/vscode-textmate': 9.2.2 '@types/hast': 3.0.4 - '@shikijs/transformers@1.10.3': - dependencies: - shiki: 1.10.3 - - '@sinclair/typebox@0.27.8': {} + '@shikijs/vscode-textmate@9.2.2': {} '@sindresorhus/is@5.4.1': {} - '@sindresorhus/merge-streams@4.0.0': {} - - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.18)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)))(svelte@4.2.18)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) - debug: 4.3.4 + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.18)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) + debug: 4.3.5 svelte: 4.2.18 - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.18)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) - debug: 4.3.4 + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.18)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)))(svelte@4.2.18)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) + debug: 4.3.5 deepmerge: 4.3.1 kleur: 4.1.5 - magic-string: 0.30.10 + magic-string: 0.30.11 svelte: 4.2.18 svelte-hmr: 0.16.0(svelte@4.2.18) - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) - vitefu: 0.2.5(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + vitefu: 0.2.5(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) transitivePeerDependencies: - supports-color @@ -5817,16 +5972,16 @@ snapshots: '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 '@types/chrome@0.0.268': dependencies: @@ -5840,6 +5995,8 @@ snapshots: '@types/estree@1.0.5': {} + '@types/estree@1.0.6': {} + '@types/filesystem@0.0.36': dependencies: '@types/filewriter': 0.0.33 @@ -5861,7 +6018,7 @@ snapshots: '@types/jsonfile@6.1.3': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.16.10 '@types/linkify-it@5.0.0': {} @@ -5871,39 +6028,41 @@ snapshots: '@types/lodash@4.14.200': {} - '@types/markdown-it@14.1.1': + '@types/markdown-it@14.1.2': dependencies: '@types/linkify-it': 5.0.0 '@types/mdurl': 2.0.0 + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.2 + '@types/mdurl@2.0.0': {} '@types/minimatch@3.0.5': {} - '@types/natural-compare@1.4.3': {} - '@types/node@20.10.3': dependencies: undici-types: 5.26.5 - '@types/node@20.14.12': + '@types/node@20.16.10': dependencies: - undici-types: 5.26.5 + undici-types: 6.19.8 '@types/normalize-path@3.0.2': {} '@types/prompts@2.4.9': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.16.10 kleur: 3.0.3 '@types/prop-types@15.7.9': {} '@types/react-dom@18.3.0': dependencies: - '@types/react': 18.3.3 + '@types/react': 18.3.11 - '@types/react@18.3.3': + '@types/react@18.3.11': dependencies: '@types/prop-types': 15.7.9 csstype: 3.1.3 @@ -5920,147 +6079,268 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.16.10 optional: true - '@vitejs/plugin-react@4.3.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8))': + '@ungap/structured-clone@1.2.0': {} + + '@unocss/astro@0.63.4(rollup@4.24.0)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))': dependencies: - '@babel/core': 7.24.7 - '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.24.7) - '@types/babel__core': 7.20.5 - react-refresh: 0.14.2 - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) + '@unocss/core': 0.63.4 + '@unocss/reset': 0.63.4 + '@unocss/vite': 0.63.4(rollup@4.24.0)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) + optionalDependencies: + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + transitivePeerDependencies: + - rollup + - supports-color + + '@unocss/cli@0.63.4(rollup@4.24.0)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) + '@unocss/config': 0.63.4 + '@unocss/core': 0.63.4 + '@unocss/preset-uno': 0.63.4 + cac: 6.7.14 + chokidar: 3.6.0 + colorette: 2.0.20 + consola: 3.2.3 + magic-string: 0.30.11 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + tinyglobby: 0.2.9 + transitivePeerDependencies: + - rollup + - supports-color + + '@unocss/config@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + unconfig: 0.5.5 transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.0.5(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8))(vue@3.4.34(typescript@5.5.4))': - dependencies: - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) - vue: 3.4.34(typescript@5.5.4) + '@unocss/core@0.63.4': {} - '@vitejs/plugin-vue@5.1.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8))(vue@3.4.34(typescript@5.5.4))': + '@unocss/extractor-arbitrary-variants@0.63.4': dependencies: - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) - vue: 3.4.34(typescript@5.5.4) + '@unocss/core': 0.63.4 - '@vitest/coverage-v8@2.0.4(vitest@2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8))': + '@unocss/inspector@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + '@unocss/rule-utils': 0.63.4 + gzip-size: 6.0.0 + sirv: 2.0.4 + + '@unocss/postcss@0.63.4(postcss@8.4.47)': + dependencies: + '@unocss/config': 0.63.4 + '@unocss/core': 0.63.4 + '@unocss/rule-utils': 0.63.4 + css-tree: 3.0.0 + postcss: 8.4.47 + tinyglobby: 0.2.9 + transitivePeerDependencies: + - supports-color + + '@unocss/preset-attributify@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + + '@unocss/preset-icons@0.63.4': + dependencies: + '@iconify/utils': 2.1.33 + '@unocss/core': 0.63.4 + ofetch: 1.4.0 + transitivePeerDependencies: + - supports-color + + '@unocss/preset-mini@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + '@unocss/extractor-arbitrary-variants': 0.63.4 + '@unocss/rule-utils': 0.63.4 + + '@unocss/preset-tagify@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + + '@unocss/preset-typography@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + '@unocss/preset-mini': 0.63.4 + + '@unocss/preset-uno@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + '@unocss/preset-mini': 0.63.4 + '@unocss/preset-wind': 0.63.4 + '@unocss/rule-utils': 0.63.4 + + '@unocss/preset-web-fonts@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + ofetch: 1.4.0 + + '@unocss/preset-wind@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + '@unocss/preset-mini': 0.63.4 + '@unocss/rule-utils': 0.63.4 + + '@unocss/reset@0.63.4': {} + + '@unocss/rule-utils@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + magic-string: 0.30.11 + + '@unocss/transformer-attributify-jsx@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + + '@unocss/transformer-compile-class@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + + '@unocss/transformer-directives@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + '@unocss/rule-utils': 0.63.4 + css-tree: 3.0.0 + + '@unocss/transformer-variant-group@0.63.4': + dependencies: + '@unocss/core': 0.63.4 + + '@unocss/vite@0.63.4(rollup@4.24.0)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) + '@unocss/config': 0.63.4 + '@unocss/core': 0.63.4 + '@unocss/inspector': 0.63.4 + chokidar: 3.6.0 + magic-string: 0.30.11 + tinyglobby: 0.2.9 + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + transitivePeerDependencies: + - rollup + - supports-color + + '@vitejs/plugin-react@4.3.2(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))': + dependencies: + '@babel/core': 7.25.7 + '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.25.7) + '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.25.7) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.2 + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-vue@5.1.4(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))(vue@3.5.11(typescript@5.6.2))': + dependencies: + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + vue: 3.5.11(typescript@5.6.2) + + '@vitest/coverage-v8@2.1.2(vitest@2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 0.2.3 - debug: 4.3.5 + debug: 4.3.7 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.1.7 - magic-string: 0.30.10 - magicast: 0.3.4 + magic-string: 0.30.11 + magicast: 0.3.5 std-env: 3.7.0 test-exclude: 7.0.1 tinyrainbow: 1.2.0 - vitest: 2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8) + vitest: 2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4) transitivePeerDependencies: - supports-color - '@vitest/expect@1.6.0': + '@vitest/expect@2.1.2': dependencies: - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - chai: 4.5.0 - - '@vitest/expect@2.0.4': - dependencies: - '@vitest/spy': 2.0.4 - '@vitest/utils': 2.0.4 + '@vitest/spy': 2.1.2 + '@vitest/utils': 2.1.2 chai: 5.1.1 tinyrainbow: 1.2.0 - '@vitest/pretty-format@2.0.4': + '@vitest/mocker@2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))': + dependencies: + '@vitest/spy': 2.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.11 + optionalDependencies: + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + + '@vitest/pretty-format@2.1.2': dependencies: tinyrainbow: 1.2.0 - '@vitest/runner@1.6.0': + '@vitest/runner@2.1.2': dependencies: - '@vitest/utils': 1.6.0 - p-limit: 5.0.0 + '@vitest/utils': 2.1.2 pathe: 1.1.2 - '@vitest/runner@2.0.4': + '@vitest/snapshot@2.1.2': dependencies: - '@vitest/utils': 2.0.4 + '@vitest/pretty-format': 2.1.2 + magic-string: 0.30.11 pathe: 1.1.2 - '@vitest/snapshot@1.6.0': - dependencies: - magic-string: 0.30.10 - pathe: 1.1.2 - pretty-format: 29.7.0 - - '@vitest/snapshot@2.0.4': - dependencies: - '@vitest/pretty-format': 2.0.4 - magic-string: 0.30.10 - pathe: 1.1.2 - - '@vitest/spy@1.6.0': - dependencies: - tinyspy: 2.2.1 - - '@vitest/spy@2.0.4': + '@vitest/spy@2.1.2': dependencies: tinyspy: 3.0.0 - '@vitest/utils@1.6.0': + '@vitest/utils@2.1.2': dependencies: - diff-sequences: 29.6.3 - estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 - - '@vitest/utils@2.0.4': - dependencies: - '@vitest/pretty-format': 2.0.4 - estree-walker: 3.0.3 + '@vitest/pretty-format': 2.1.2 loupe: 3.1.1 tinyrainbow: 1.2.0 - '@vue/compiler-core@3.4.34': + '@vue/compiler-core@3.5.11': dependencies: - '@babel/parser': 7.24.7 - '@vue/shared': 3.4.34 + '@babel/parser': 7.25.6 + '@vue/shared': 3.5.11 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.0 - '@vue/compiler-dom@3.4.34': + '@vue/compiler-dom@3.5.11': dependencies: - '@vue/compiler-core': 3.4.34 - '@vue/shared': 3.4.34 + '@vue/compiler-core': 3.5.11 + '@vue/shared': 3.5.11 - '@vue/compiler-sfc@3.4.34': + '@vue/compiler-sfc@3.5.11': dependencies: - '@babel/parser': 7.24.7 - '@vue/compiler-core': 3.4.34 - '@vue/compiler-dom': 3.4.34 - '@vue/compiler-ssr': 3.4.34 - '@vue/shared': 3.4.34 + '@babel/parser': 7.25.6 + '@vue/compiler-core': 3.5.11 + '@vue/compiler-dom': 3.5.11 + '@vue/compiler-ssr': 3.5.11 + '@vue/shared': 3.5.11 estree-walker: 2.0.2 magic-string: 0.30.11 - postcss: 8.4.39 + postcss: 8.4.47 source-map-js: 1.2.0 - '@vue/compiler-ssr@3.4.34': + '@vue/compiler-ssr@3.5.11': dependencies: - '@vue/compiler-dom': 3.4.34 - '@vue/shared': 3.4.34 + '@vue/compiler-dom': 3.5.11 + '@vue/shared': 3.5.11 - '@vue/devtools-api@7.3.6': + '@vue/devtools-api@7.4.6': dependencies: - '@vue/devtools-kit': 7.3.6 + '@vue/devtools-kit': 7.4.6 - '@vue/devtools-kit@7.3.6': + '@vue/devtools-kit@7.4.6': dependencies: - '@vue/devtools-shared': 7.3.6 + '@vue/devtools-shared': 7.4.6 birpc: 0.2.17 hookable: 5.5.3 mitt: 3.0.1 @@ -6068,62 +6348,60 @@ snapshots: speakingurl: 14.0.1 superjson: 2.2.1 - '@vue/devtools-shared@7.3.6': + '@vue/devtools-shared@7.4.6': dependencies: rfdc: 1.4.1 - '@vue/reactivity@3.4.34': + '@vue/reactivity@3.5.11': dependencies: - '@vue/shared': 3.4.34 + '@vue/shared': 3.5.11 - '@vue/runtime-core@3.4.34': + '@vue/runtime-core@3.5.11': dependencies: - '@vue/reactivity': 3.4.34 - '@vue/shared': 3.4.34 + '@vue/reactivity': 3.5.11 + '@vue/shared': 3.5.11 - '@vue/runtime-dom@3.4.34': + '@vue/runtime-dom@3.5.11': dependencies: - '@vue/reactivity': 3.4.34 - '@vue/runtime-core': 3.4.34 - '@vue/shared': 3.4.34 + '@vue/reactivity': 3.5.11 + '@vue/runtime-core': 3.5.11 + '@vue/shared': 3.5.11 csstype: 3.1.3 - '@vue/server-renderer@3.4.34(vue@3.4.34(typescript@5.5.4))': + '@vue/server-renderer@3.5.11(vue@3.5.11(typescript@5.6.2))': dependencies: - '@vue/compiler-ssr': 3.4.34 - '@vue/shared': 3.4.34 - vue: 3.4.34(typescript@5.5.4) + '@vue/compiler-ssr': 3.5.11 + '@vue/shared': 3.5.11 + vue: 3.5.11(typescript@5.6.2) - '@vue/shared@3.4.31': {} + '@vue/shared@3.5.11': {} - '@vue/shared@3.4.34': {} - - '@vueuse/core@10.11.0(vue@3.4.34(typescript@5.5.4))': + '@vueuse/core@11.1.0(vue@3.5.11(typescript@5.6.2))': dependencies: '@types/web-bluetooth': 0.0.20 - '@vueuse/metadata': 10.11.0 - '@vueuse/shared': 10.11.0(vue@3.4.34(typescript@5.5.4)) - vue-demi: 0.14.8(vue@3.4.34(typescript@5.5.4)) + '@vueuse/metadata': 11.1.0 + '@vueuse/shared': 11.1.0(vue@3.5.11(typescript@5.6.2)) + vue-demi: 0.14.10(vue@3.5.11(typescript@5.6.2)) transitivePeerDependencies: - '@vue/composition-api' - vue - '@vueuse/integrations@10.11.0(focus-trap@7.5.4)(vue@3.4.34(typescript@5.5.4))': + '@vueuse/integrations@11.1.0(focus-trap@7.5.4)(vue@3.5.11(typescript@5.6.2))': dependencies: - '@vueuse/core': 10.11.0(vue@3.4.34(typescript@5.5.4)) - '@vueuse/shared': 10.11.0(vue@3.4.34(typescript@5.5.4)) - vue-demi: 0.14.8(vue@3.4.34(typescript@5.5.4)) + '@vueuse/core': 11.1.0(vue@3.5.11(typescript@5.6.2)) + '@vueuse/shared': 11.1.0(vue@3.5.11(typescript@5.6.2)) + vue-demi: 0.14.10(vue@3.5.11(typescript@5.6.2)) optionalDependencies: focus-trap: 7.5.4 transitivePeerDependencies: - '@vue/composition-api' - vue - '@vueuse/metadata@10.11.0': {} + '@vueuse/metadata@11.1.0': {} - '@vueuse/shared@10.11.0(vue@3.4.34(typescript@5.5.4))': + '@vueuse/shared@11.1.0(vue@3.5.11(typescript@5.6.2))': dependencies: - vue-demi: 0.14.8(vue@3.4.34(typescript@5.5.4)) + vue-demi: 0.14.10(vue@3.5.11(typescript@5.6.2)) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -6138,10 +6416,6 @@ snapshots: '@webext-core/match-patterns@1.0.3': {} - acorn-walk@8.3.3: - dependencies: - acorn: 8.12.1 - acorn@8.12.1: {} adm-zip@0.5.10: {} @@ -6171,6 +6445,10 @@ snapshots: dependencies: type-fest: 3.13.1 + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + ansi-regex@5.0.1: {} ansi-regex@6.0.1: {} @@ -6185,8 +6463,6 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@5.2.0: {} - ansi-styles@6.2.1: {} any-promise@1.3.0: {} @@ -6200,17 +6476,10 @@ snapshots: dependencies: dequal: 2.0.3 - array-buffer-byte-length@1.0.0: - dependencies: - call-bind: 1.0.2 - is-array-buffer: 3.0.2 - array-differ@4.0.0: {} array-union@3.0.1: {} - assertion-error@1.1.0: {} - assertion-error@2.0.1: {} async-mutex@0.5.0: @@ -6227,12 +6496,10 @@ snapshots: caniuse-lite: 1.0.30001633 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.1 + picocolors: 1.1.0 postcss: 8.4.39 postcss-value-parser: 4.2.0 - available-typed-arrays@1.0.5: {} - axobject-query@4.0.0: dependencies: dequal: 2.0.3 @@ -6242,7 +6509,7 @@ snapshots: '@babel/core': 7.24.7 '@babel/helper-module-imports': 7.18.6 '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.7) - '@babel/types': 7.24.7 + '@babel/types': 7.25.6 html-entities: 2.3.3 validate-html-nesting: 1.2.2 @@ -6306,6 +6573,13 @@ snapshots: node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.1) + browserslist@4.24.0: + dependencies: + caniuse-lite: 1.0.30001666 + electron-to-chromium: 1.5.32 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.0) + buffer-crc32@0.2.13: {} buffer-from@1.1.2: {} @@ -6325,6 +6599,11 @@ snapshots: dependencies: run-applescript: 7.0.0 + bundle-require@5.0.0(esbuild@0.21.5): + dependencies: + esbuild: 0.21.5 + load-tsconfig: 0.2.5 + bunyan@1.8.15: optionalDependencies: dtrace-provider: 0.8.8 @@ -6332,7 +6611,7 @@ snapshots: mv: 2.1.1 safe-json-stringify: 1.2.0 - c12@1.10.0: + c12@1.11.2(magicast@0.3.5): dependencies: chokidar: 3.6.0 confbox: 0.1.7 @@ -6341,28 +6620,13 @@ snapshots: giget: 1.2.3 jiti: 1.21.6 mlly: 1.7.1 - ohash: 1.1.3 + ohash: 1.1.4 pathe: 1.1.2 perfect-debounce: 1.0.0 pkg-types: 1.2.0 - rc9: 2.1.1 - - c12@1.11.1(magicast@0.3.4): - dependencies: - chokidar: 3.6.0 - confbox: 0.1.7 - defu: 6.1.4 - dotenv: 16.4.5 - giget: 1.2.3 - jiti: 1.21.6 - mlly: 1.7.1 - ohash: 1.1.3 - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.1.1 rc9: 2.1.2 optionalDependencies: - magicast: 0.3.4 + magicast: 0.3.5 cac@6.7.14: {} @@ -6378,11 +6642,6 @@ snapshots: normalize-url: 8.0.0 responselike: 3.0.0 - call-bind@1.0.2: - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.2.1 - camelcase@7.0.1: {} caniuse-api@3.0.0: @@ -6394,15 +6653,9 @@ snapshots: caniuse-lite@1.0.30001633: {} - chai@4.5.0: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.1.0 + caniuse-lite@1.0.30001666: {} + + ccount@2.0.1: {} chai@5.1.1: dependencies: @@ -6425,27 +6678,28 @@ snapshots: chalk@5.3.0: {} - changelogen@0.5.5: + changelogen@0.5.7(magicast@0.3.5): dependencies: - c12: 1.10.0 + c12: 1.11.2(magicast@0.3.5) colorette: 2.0.20 consola: 3.2.3 convert-gitmoji: 0.1.5 - execa: 8.0.1 mri: 1.2.0 node-fetch-native: 1.6.4 - ofetch: 1.3.3 - open: 9.1.0 + ofetch: 1.4.0 + open: 10.1.0 pathe: 1.1.2 - pkg-types: 1.0.3 + pkg-types: 1.2.0 scule: 1.3.0 - semver: 7.5.4 - std-env: 3.6.0 - yaml: 2.5.0 + semver: 7.6.3 + std-env: 3.7.0 + yaml: 2.5.1 + transitivePeerDependencies: + - magicast - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} check-error@2.1.1: {} @@ -6461,11 +6715,15 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.1: + dependencies: + readdirp: 4.0.2 + chownr@2.0.0: {} chrome-launcher@1.1.0: dependencies: - '@types/node': 20.14.12 + '@types/node': 20.16.10 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.1 @@ -6523,7 +6781,7 @@ snapshots: code-red@1.0.4: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 acorn: 8.12.1 estree-walker: 3.0.3 periscopic: 3.1.0 @@ -6554,6 +6812,8 @@ snapshots: colorette@2.0.20: {} + comma-separated-tokens@2.0.3: {} + commander@12.1.0: {} commander@2.9.0: @@ -6602,14 +6862,6 @@ snapshots: core-util-is@1.0.3: {} - cross-spawn@6.0.5: - dependencies: - nice-try: 1.0.5 - path-key: 2.0.1 - semver: 5.7.1 - shebang-command: 1.2.0 - which: 1.3.1 - cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -6642,6 +6894,11 @@ snapshots: mdn-data: 2.0.30 source-map-js: 1.2.0 + css-tree@3.0.0: + dependencies: + mdn-data: 2.10.0 + source-map-js: 1.2.1 + css-what@6.1.0: {} cssesc@3.0.0: {} @@ -6712,14 +6969,14 @@ snapshots: dependencies: ms: 2.1.2 + debug@4.3.7: + dependencies: + ms: 2.1.3 + decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 - deep-eql@4.1.4: - dependencies: - type-detect: 4.1.0 - deep-eql@5.0.2: {} deep-extend@0.6.0: {} @@ -6755,24 +7012,19 @@ snapshots: define-lazy-prop@3.0.0: {} - define-properties@1.2.0: - dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - defu@6.1.4: {} dependency-graph@1.0.0: {} dequal@2.0.3: {} - destr@2.0.2: {} - destr@2.0.3: {} detect-libc@2.0.3: {} - diff-sequences@29.6.3: {} + devlop@1.1.0: + dependencies: + dequal: 2.0.3 dir-glob@3.0.1: dependencies: @@ -6807,10 +7059,14 @@ snapshots: nan: 2.17.0 optional: true + duplexer@0.1.2: {} + eastasianwidth@0.2.0: {} electron-to-chromium@1.4.802: {} + electron-to-chromium@1.5.32: {} + emoji-regex@10.3.0: {} emoji-regex@8.0.0: {} @@ -6823,59 +7079,12 @@ snapshots: entities@4.5.0: {} + environment@1.1.0: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - es-abstract@1.21.2: - dependencies: - array-buffer-byte-length: 1.0.0 - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-set-tostringtag: 2.0.1 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.5 - get-intrinsic: 1.2.1 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has: 1.0.3 - has-property-descriptors: 1.0.0 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.5 - is-array-buffer: 3.0.2 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.10 - is-weakref: 1.0.2 - object-inspect: 1.12.3 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.5.0 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.7 - string.prototype.trimend: 1.0.6 - string.prototype.trimstart: 1.0.6 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.9 - - es-set-tostringtag@2.0.1: - dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 - has-tostringtag: 1.0.0 - - es-to-primitive@1.2.1: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - es6-error@4.1.1: {} esbuild@0.19.12: @@ -6961,6 +7170,8 @@ snapshots: escalade@3.1.2: {} + escalade@3.2.0: {} + escape-goat@4.0.0: {} escape-string-regexp@1.0.5: {} @@ -6973,7 +7184,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 eventemitter3@5.0.1: {} @@ -7013,21 +7224,6 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 - execa@9.3.1: - dependencies: - '@sindresorhus/merge-streams': 4.0.0 - cross-spawn: 7.0.3 - figures: 6.1.0 - get-stream: 9.0.1 - human-signals: 8.0.0 - is-plain-obj: 4.1.0 - is-stream: 4.0.1 - npm-run-path: 5.3.0 - pretty-ms: 9.0.0 - signal-exit: 4.1.0 - strip-final-newline: 4.0.0 - yoctocolors: 2.0.2 - extract-zip@2.0.1: dependencies: debug: 4.3.4 @@ -7054,11 +7250,11 @@ snapshots: dependencies: pend: 1.2.0 - figures@6.1.0: - dependencies: - is-unicode-supported: 2.0.0 + fdir@6.4.2(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 - filesize@10.1.4: {} + filesize@10.1.6: {} fill-range@7.1.1: dependencies: @@ -7072,16 +7268,10 @@ snapshots: minimist: 1.2.8 xml2js: 0.5.0 - flat@5.0.2: {} - focus-trap@7.5.4: dependencies: tabbable: 6.2.0 - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - foreground-child@3.2.1: dependencies: cross-spawn: 7.0.3 @@ -7117,15 +7307,6 @@ snapshots: function-bind@1.1.1: {} - function.prototype.name@1.1.5: - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - functions-have-names: 1.2.3 - - functions-have-names@1.2.3: {} - fx-runner@1.4.0: dependencies: commander: 2.9.0 @@ -7143,13 +7324,6 @@ snapshots: get-func-name@2.0.2: {} - get-intrinsic@1.2.1: - dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-proto: 1.0.1 - has-symbols: 1.0.3 - get-port@7.1.0: {} get-stream@5.2.0: @@ -7160,16 +7334,6 @@ snapshots: get-stream@8.0.1: {} - get-stream@9.0.1: - dependencies: - '@sec-ant/readable-stream': 0.4.1 - is-stream: 4.0.1 - - get-symbol-description@1.0.0: - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - get-tsconfig@4.7.5: dependencies: resolve-pkg-maps: 1.0.0 @@ -7180,8 +7344,8 @@ snapshots: consola: 3.2.3 defu: 6.1.4 node-fetch-native: 1.6.4 - nypm: 0.3.9 - ohash: 1.1.3 + nypm: 0.3.12 + ohash: 1.1.4 pathe: 1.1.2 tar: 6.2.1 @@ -7223,10 +7387,6 @@ snapshots: globals@11.12.0: {} - globalthis@1.0.3: - dependencies: - define-properties: 1.2.0 - globby@13.2.2: dependencies: dir-glob: 3.0.1 @@ -7235,10 +7395,6 @@ snapshots: merge2: 1.4.1 slash: 4.0.0 - gopd@1.0.1: - dependencies: - get-intrinsic: 1.2.1 - got@12.6.1: dependencies: '@sindresorhus/is': 5.4.1 @@ -7261,53 +7417,56 @@ snapshots: growly@1.3.0: {} + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + happy-dom@14.12.3: dependencies: entities: 4.5.0 webidl-conversions: 7.0.0 whatwg-mimetype: 3.0.0 - has-bigints@1.0.2: {} - has-flag@3.0.0: {} has-flag@4.0.0: {} - has-property-descriptors@1.0.0: - dependencies: - get-intrinsic: 1.2.1 - - has-proto@1.0.1: {} - - has-symbols@1.0.3: {} - - has-tostringtag@1.0.0: - dependencies: - has-symbols: 1.0.3 - has-yarn@3.0.0: {} has@1.0.3: dependencies: function-bind: 1.1.1 - hasha@6.0.0: + hast-util-to-html@9.0.3: dependencies: - is-stream: 3.0.0 - type-fest: 4.20.0 + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 highlight.js@10.7.3: {} hookable@5.5.3: {} - hosted-git-info@2.8.9: {} - html-entities@2.3.3: {} html-escaper@2.0.2: {} html-escaper@3.0.3: {} + html-void-elements@3.0.0: {} + htmlparser2@9.1.0: dependencies: domelementtype: 2.3.0 @@ -7328,8 +7487,6 @@ snapshots: human-signals@5.0.0: {} - human-signals@8.0.0: {} - ieee754@1.2.1: {} ignore-walk@5.0.1: @@ -7344,6 +7501,18 @@ snapshots: import-lazy@4.0.0: {} + importx@0.4.4: + dependencies: + bundle-require: 5.0.0(esbuild@0.21.5) + debug: 4.3.7 + esbuild: 0.21.5 + jiti: 2.0.0-beta.3 + jiti-v1: jiti@1.21.6 + pathe: 1.1.2 + tsx: 4.19.1 + transitivePeerDependencies: + - supports-color + imurmurhash@0.1.4: {} inflight@1.0.6: @@ -7357,45 +7526,22 @@ snapshots: ini@2.0.0: {} - internal-slot@1.0.5: - dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 - side-channel: 1.0.4 - is-absolute@0.1.7: dependencies: is-relative: 0.1.3 - is-array-buffer@3.0.2: - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-typed-array: 1.1.10 - is-arrayish@0.2.1: {} is-arrayish@0.3.2: {} - is-bigint@1.0.4: - dependencies: - has-bigints: 1.0.2 - is-binary-path@2.1.0: dependencies: binary-extensions: 2.2.0 - is-boolean-object@1.1.2: - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - is-builtin-module@3.2.1: dependencies: builtin-modules: 3.3.0 - is-callable@1.2.7: {} - is-ci@3.0.1: dependencies: ci-info: 3.8.0 @@ -7404,10 +7550,6 @@ snapshots: dependencies: has: 1.0.3 - is-date-object@1.0.5: - dependencies: - has-tostringtag: 1.0.0 - is-docker@2.2.1: {} is-docker@3.0.0: {} @@ -7439,22 +7581,14 @@ snapshots: is-module@1.0.0: {} - is-negative-zero@2.0.2: {} - is-npm@6.0.0: {} - is-number-object@1.0.7: - dependencies: - has-tostringtag: 1.0.0 - is-number@7.0.0: {} is-obj@2.0.0: {} is-path-inside@3.0.3: {} - is-plain-obj@4.1.0: {} - is-plain-object@2.0.4: dependencies: isobject: 3.0.1 @@ -7469,51 +7603,20 @@ snapshots: is-reference@3.0.2: dependencies: - '@types/estree': 1.0.5 - - is-regex@1.1.4: - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 + '@types/estree': 1.0.6 is-relative@0.1.3: {} - is-shared-array-buffer@1.0.2: - dependencies: - call-bind: 1.0.2 - is-stream@2.0.1: {} is-stream@3.0.0: {} - is-stream@4.0.1: {} - - is-string@1.0.7: - dependencies: - has-tostringtag: 1.0.0 - - is-symbol@1.0.4: - dependencies: - has-symbols: 1.0.3 - - is-typed-array@1.1.10: - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - is-typedarray@1.0.0: {} is-unicode-supported@1.3.0: {} is-unicode-supported@2.0.0: {} - is-weakref@1.0.2: - dependencies: - call-bind: 1.0.2 - is-what@4.1.16: {} is-wsl@2.2.0: @@ -7545,7 +7648,7 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.25 - debug: 4.3.5 + debug: 4.3.7 istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -7563,15 +7666,17 @@ snapshots: jiti@1.21.6: {} + jiti@2.0.0-beta.3: {} + js-tokens@4.0.0: {} js-tokens@9.0.0: {} jsesc@2.5.2: {} - json-buffer@3.0.1: {} + jsesc@3.0.2: {} - json-parse-better-errors@1.0.2: {} + json-buffer@3.0.1: {} json-parse-even-better-errors@3.0.0: {} @@ -7600,6 +7705,8 @@ snapshots: kleur@4.1.5: {} + kolorist@1.8.0: {} + latest-version@7.0.0: dependencies: package-json: 8.1.1 @@ -7619,7 +7726,7 @@ snapshots: lines-and-columns@2.0.3: {} - linkedom@0.18.4: + linkedom@0.18.5: dependencies: css-select: 5.1.0 cssom: 0.5.0 @@ -7627,45 +7734,40 @@ snapshots: htmlparser2: 9.1.0 uhyphen: 0.2.0 - lint-staged@15.2.7: + lint-staged@15.2.10: dependencies: chalk: 5.3.0 commander: 12.1.0 - debug: 4.3.4 + debug: 4.3.7 execa: 8.0.1 lilconfig: 3.1.2 - listr2: 8.2.1 - micromatch: 4.0.7 + listr2: 8.2.5 + micromatch: 4.0.8 pidtree: 0.6.0 string-argv: 0.3.2 - yaml: 2.4.5 + yaml: 2.5.1 transitivePeerDependencies: - supports-color - listr2@8.0.2: - dependencies: - cli-truncate: 4.0.0 - colorette: 2.0.20 - eventemitter3: 5.0.1 - log-update: 6.0.0 - rfdc: 1.3.1 - wrap-ansi: 9.0.0 - listr2@8.2.1: dependencies: cli-truncate: 4.0.0 colorette: 2.0.20 eventemitter3: 5.0.1 log-update: 6.0.0 - rfdc: 1.3.1 + rfdc: 1.4.1 wrap-ansi: 9.0.0 - load-json-file@4.0.0: + listr2@8.2.5: dependencies: - graceful-fs: 4.2.11 - parse-json: 4.0.0 - pify: 3.0.0 - strip-bom: 3.0.0 + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 + + load-tsconfig@0.2.5: {} local-pkg@0.5.0: dependencies: @@ -7704,14 +7806,18 @@ snapshots: strip-ansi: 7.1.0 wrap-ansi: 9.0.0 + log-update@6.1.0: + dependencies: + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - loupe@3.1.1: dependencies: get-func-name: 2.0.2 @@ -7724,10 +7830,6 @@ snapshots: dependencies: yallist: 3.1.1 - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - lunr@2.3.9: {} magic-string@0.30.10: @@ -7738,10 +7840,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - magicast@0.3.4: + magicast@0.3.5: dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 source-map-js: 1.2.0 make-dir@4.0.0: @@ -7752,15 +7854,29 @@ snapshots: mark.js@8.11.1: {} + markdown-it-footnote@4.0.0(patch_hash=ue34jdgdx43siqdj557feoepzq): {} + marked@4.3.0: {} marky@1.2.5: {} + mdast-util-to-hast@13.2.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + mdn-data@2.0.28: {} mdn-data@2.0.30: {} - memorystream@0.3.1: {} + mdn-data@2.10.0: {} merge-anything@5.1.7: dependencies: @@ -7770,12 +7886,29 @@ snapshots: merge2@1.4.1: {} + micromark-util-character@2.1.0: + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-encode@2.0.0: {} + + micromark-util-sanitize-uri@2.0.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + + micromark-util-symbol@2.0.0: {} + + micromark-util-types@2.0.0: {} + micromatch@4.0.5: dependencies: braces: 3.0.3 picomatch: 2.3.1 - micromatch@4.0.7: + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.1 @@ -7820,7 +7953,7 @@ snapshots: minipass@7.1.2: {} - minisearch@7.0.2: {} + minisearch@7.1.0: {} minizlib@2.1.2: dependencies: @@ -7838,7 +7971,7 @@ snapshots: mkdirp@3.0.1: {} - mkdist@1.5.4(sass@1.77.8)(typescript@5.5.4): + mkdist@1.5.4(sass@1.79.4)(typescript@5.6.2): dependencies: autoprefixer: 10.4.19(postcss@8.4.39) citty: 0.1.6 @@ -7854,8 +7987,8 @@ snapshots: postcss-nested: 6.0.1(postcss@8.4.39) semver: 7.6.2 optionalDependencies: - sass: 1.77.8 - typescript: 5.5.4 + sass: 1.79.4 + typescript: 5.6.2 mlly@1.7.1: dependencies: @@ -7869,10 +8002,14 @@ snapshots: mri@1.2.0: {} + mrmime@2.0.0: {} + ms@2.0.0: {} ms@2.1.2: {} + ms@2.1.3: {} + multimatch@6.0.0: dependencies: '@types/minimatch': 3.0.5 @@ -7896,15 +8033,13 @@ snapshots: nan@2.17.0: optional: true - nanoid@3.3.7: {} + nano-spawn@0.1.0: {} - natural-compare@1.4.0: {} + nanoid@3.3.7: {} ncp@2.0.0: optional: true - nice-try@1.0.5: {} - node-fetch-native@1.6.4: {} node-forge@1.3.1: {} @@ -7920,12 +8055,7 @@ snapshots: node-releases@2.0.14: {} - normalize-package-data@2.5.0: - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.2 - semver: 5.7.1 - validate-npm-package-license: 3.0.4 + node-releases@2.0.18: {} normalize-path@3.0.0: {} @@ -7946,18 +8076,6 @@ snapshots: npm-bundled: 2.0.1 npm-normalize-package-bin: 2.0.0 - npm-run-all@4.1.5: - dependencies: - ansi-styles: 3.2.1 - chalk: 2.4.2 - cross-spawn: 6.0.5 - memorystream: 0.3.1 - minimatch: 3.1.2 - pidtree: 0.3.1 - read-pkg: 3.0.0 - shell-quote: 1.8.1 - string.prototype.padend: 3.1.4 - npm-run-path@4.0.1: dependencies: path-key: 3.1.1 @@ -7970,35 +8088,24 @@ snapshots: dependencies: boolbase: 1.0.0 - nypm@0.3.9: + nypm@0.3.12: dependencies: citty: 0.1.6 consola: 3.2.3 execa: 8.0.1 pathe: 1.1.2 - pkg-types: 1.1.1 - ufo: 1.5.3 + pkg-types: 1.2.0 + ufo: 1.5.4 object-assign@4.1.1: {} - object-inspect@1.12.3: {} - - object-keys@1.1.1: {} - - object.assign@4.1.4: + ofetch@1.4.0: dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - has-symbols: 1.0.3 - object-keys: 1.1.1 - - ofetch@1.3.3: - dependencies: - destr: 2.0.2 + destr: 2.0.3 node-fetch-native: 1.6.4 - ufo: 1.4.0 + ufo: 1.5.4 - ohash@1.1.3: {} + ohash@1.1.4: {} once@1.4.0: dependencies: @@ -8016,6 +8123,10 @@ snapshots: dependencies: mimic-function: 5.0.1 + oniguruma-to-js@0.4.3: + dependencies: + regex: 4.3.3 + open@10.1.0: dependencies: default-browser: 5.2.1 @@ -8062,25 +8173,19 @@ snapshots: os-shim@0.1.3: {} - oxlint@0.9.1: + oxlint@0.9.9: optionalDependencies: - '@oxlint/darwin-arm64': 0.9.1 - '@oxlint/darwin-x64': 0.9.1 - '@oxlint/linux-arm64-gnu': 0.9.1 - '@oxlint/linux-arm64-musl': 0.9.1 - '@oxlint/linux-x64-gnu': 0.9.1 - '@oxlint/linux-x64-musl': 0.9.1 - '@oxlint/win32-arm64': 0.9.1 - '@oxlint/win32-x64': 0.9.1 + '@oxlint/darwin-arm64': 0.9.9 + '@oxlint/darwin-x64': 0.9.9 + '@oxlint/linux-arm64-gnu': 0.9.9 + '@oxlint/linux-arm64-musl': 0.9.9 + '@oxlint/linux-x64-gnu': 0.9.9 + '@oxlint/linux-x64-musl': 0.9.9 + '@oxlint/win32-arm64': 0.9.9 + '@oxlint/win32-x64': 0.9.9 p-cancelable@3.0.0: {} - p-limit@5.0.0: - dependencies: - yocto-queue: 1.1.1 - - p-map@7.0.2: {} - package-json-from-dist@1.0.0: {} package-json@8.1.1: @@ -8090,12 +8195,9 @@ snapshots: registry-url: 6.0.1 semver: 7.6.3 - pako@1.0.11: {} + package-manager-detector@0.2.2: {} - parse-json@4.0.0: - dependencies: - error-ex: 1.3.2 - json-parse-better-errors: 1.0.2 + pako@1.0.11: {} parse-json@7.1.1: dependencies: @@ -8105,8 +8207,6 @@ snapshots: lines-and-columns: 2.0.3 type-fest: 3.13.1 - parse-ms@4.0.0: {} - parse5-htmlparser2-tree-adapter@6.0.1: dependencies: parse5: 6.0.1 @@ -8118,8 +8218,6 @@ snapshots: path-is-absolute@1.0.1: optional: true - path-key@2.0.1: {} - path-key@3.1.1: {} path-key@4.0.0: {} @@ -8131,16 +8229,10 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 - path-type@3.0.0: - dependencies: - pify: 3.0.0 - path-type@4.0.0: {} pathe@1.1.2: {} - pathval@1.1.1: {} - pathval@2.0.0: {} pend@1.2.0: {} @@ -8149,32 +8241,18 @@ snapshots: periscopic@3.1.0: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 estree-walker: 3.0.3 is-reference: 3.0.2 - picocolors@1.0.1: {} + picocolors@1.1.0: {} picomatch@2.3.1: {} - pidtree@0.3.1: {} + picomatch@4.0.2: {} pidtree@0.6.0: {} - pify@3.0.0: {} - - pkg-types@1.0.3: - dependencies: - jsonc-parser: 3.2.0 - mlly: 1.7.1 - pathe: 1.1.2 - - pkg-types@1.1.1: - dependencies: - confbox: 0.1.7 - mlly: 1.7.1 - pathe: 1.1.2 - pkg-types@1.1.3: dependencies: confbox: 0.1.7 @@ -8351,25 +8429,21 @@ snapshots: postcss@8.4.39: dependencies: nanoid: 3.3.7 - picocolors: 1.0.1 + picocolors: 1.1.0 source-map-js: 1.2.0 + postcss@8.4.47: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.0 + source-map-js: 1.2.1 + preact@10.18.1: {} prettier@3.3.3: {} pretty-bytes@6.1.1: {} - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - pretty-ms@9.0.0: - dependencies: - parse-ms: 4.0.0 - process-nextick-args@2.0.1: {} promise-toolbox@0.21.0: @@ -8387,15 +8461,17 @@ snapshots: retry: 0.12.0 signal-exit: 3.0.7 + property-information@6.5.0: {} + proto-list@1.2.4: {} - publint@0.2.9: + publint@0.2.11: dependencies: npm-packlist: 5.1.3 - picocolors: 1.0.1 + picocolors: 1.1.0 sade: 1.8.1 - publish-browser-extension@2.1.3: + publish-browser-extension@2.2.2: dependencies: cac: 6.7.14 cli-highlight: 2.1.11 @@ -8403,11 +8479,11 @@ snapshots: dotenv: 16.4.5 extract-zip: 2.0.1 formdata-node: 6.0.3 - listr2: 8.0.2 + listr2: 8.2.1 lodash.camelcase: 4.3.0 lodash.kebabcase: 4.1.1 lodash.snakecase: 4.1.1 - ofetch: 1.3.3 + ofetch: 1.4.0 open: 9.1.0 ora: 6.3.1 prompts: 2.4.2 @@ -8428,12 +8504,6 @@ snapshots: quick-lru@5.1.1: {} - rc9@2.1.1: - dependencies: - defu: 6.1.4 - destr: 2.0.2 - flat: 5.0.2 - rc9@2.1.2: dependencies: defu: 6.1.4 @@ -8452,20 +8522,12 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-is@18.3.1: {} - react-refresh@0.14.2: {} react@18.3.1: dependencies: loose-envify: 1.4.0 - read-pkg@3.0.0: - dependencies: - load-json-file: 4.0.0 - normalize-package-data: 2.5.0 - path-type: 3.0.0 - readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -8486,13 +8548,11 @@ snapshots: dependencies: picomatch: 2.3.1 + readdirp@4.0.2: {} + regenerator-runtime@0.14.0: {} - regexp.prototype.flags@1.5.0: - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - functions-have-names: 1.2.3 + regex@4.3.3: {} registry-auth-token@5.0.2: dependencies: @@ -8532,8 +8592,6 @@ snapshots: reusify@1.0.4: {} - rfdc@1.3.1: {} - rfdc@1.4.1: {} rimraf@2.4.5: @@ -8541,11 +8599,11 @@ snapshots: glob: 6.0.4 optional: true - rollup-plugin-dts@6.1.1(rollup@3.29.4)(typescript@5.5.4): + rollup-plugin-dts@6.1.1(rollup@3.29.4)(typescript@5.6.2): dependencies: magic-string: 0.30.10 rollup: 3.29.4 - typescript: 5.5.4 + typescript: 5.6.2 optionalDependencies: '@babel/code-frame': 7.24.7 @@ -8553,26 +8611,26 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - rollup@4.19.0: + rollup@4.24.0: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.19.0 - '@rollup/rollup-android-arm64': 4.19.0 - '@rollup/rollup-darwin-arm64': 4.19.0 - '@rollup/rollup-darwin-x64': 4.19.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.19.0 - '@rollup/rollup-linux-arm-musleabihf': 4.19.0 - '@rollup/rollup-linux-arm64-gnu': 4.19.0 - '@rollup/rollup-linux-arm64-musl': 4.19.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.19.0 - '@rollup/rollup-linux-riscv64-gnu': 4.19.0 - '@rollup/rollup-linux-s390x-gnu': 4.19.0 - '@rollup/rollup-linux-x64-gnu': 4.19.0 - '@rollup/rollup-linux-x64-musl': 4.19.0 - '@rollup/rollup-win32-arm64-msvc': 4.19.0 - '@rollup/rollup-win32-ia32-msvc': 4.19.0 - '@rollup/rollup-win32-x64-msvc': 4.19.0 + '@rollup/rollup-android-arm-eabi': 4.24.0 + '@rollup/rollup-android-arm64': 4.24.0 + '@rollup/rollup-darwin-arm64': 4.24.0 + '@rollup/rollup-darwin-x64': 4.24.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 + '@rollup/rollup-linux-arm-musleabihf': 4.24.0 + '@rollup/rollup-linux-arm64-gnu': 4.24.0 + '@rollup/rollup-linux-arm64-musl': 4.24.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 + '@rollup/rollup-linux-riscv64-gnu': 4.24.0 + '@rollup/rollup-linux-s390x-gnu': 4.24.0 + '@rollup/rollup-linux-x64-gnu': 4.24.0 + '@rollup/rollup-linux-x64-musl': 4.24.0 + '@rollup/rollup-win32-arm64-msvc': 4.24.0 + '@rollup/rollup-win32-ia32-msvc': 4.24.0 + '@rollup/rollup-win32-x64-msvc': 4.24.0 fsevents: 2.3.3 run-applescript@5.0.0: @@ -8594,17 +8652,11 @@ snapshots: safe-json-stringify@1.2.0: optional: true - safe-regex-test@1.0.0: + sass@1.79.4: dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-regex: 1.1.4 - - sass@1.77.8: - dependencies: - chokidar: 3.6.0 + chokidar: 4.0.1 immutable: 4.3.4 - source-map-js: 1.2.0 + source-map-js: 1.2.1 sax@1.2.4: {} @@ -8620,14 +8672,8 @@ snapshots: dependencies: semver: 7.6.3 - semver@5.7.1: {} - semver@6.3.1: {} - semver@7.5.4: - dependencies: - lru-cache: 6.0.0 - semver@7.6.2: {} semver@7.6.3: {} @@ -8671,22 +8717,14 @@ snapshots: '@img/sharp-win32-ia32': 0.33.5 '@img/sharp-win32-x64': 0.33.5 - shebang-command@1.2.0: - dependencies: - shebang-regex: 1.0.0 - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - shebang-regex@1.0.0: {} - shebang-regex@3.0.0: {} shell-quote@1.7.3: {} - shell-quote@1.8.1: {} - shellwords@0.1.1: {} shiki@0.14.5: @@ -8696,17 +8734,15 @@ snapshots: vscode-oniguruma: 1.7.0 vscode-textmate: 8.0.0 - shiki@1.10.3: + shiki@1.21.0: dependencies: - '@shikijs/core': 1.10.3 + '@shikijs/core': 1.21.0 + '@shikijs/engine-javascript': 1.21.0 + '@shikijs/engine-oniguruma': 1.21.0 + '@shikijs/types': 1.21.0 + '@shikijs/vscode-textmate': 9.2.2 '@types/hast': 3.0.4 - side-channel@1.0.4: - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - object-inspect: 1.12.3 - siginfo@2.0.0: {} signal-exit@3.0.7: {} @@ -8719,6 +8755,12 @@ snapshots: dependencies: is-arrayish: 0.3.2 + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.28 + mrmime: 2.0.0 + totalist: 3.0.1 + sisteransi@1.0.5: {} slash@4.0.0: {} @@ -8733,23 +8775,25 @@ snapshots: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 - solid-js@1.8.19: + solid-js@1.9.1: dependencies: csstype: 3.1.3 seroval: 1.1.0 seroval-plugins: 1.1.0(seroval@1.1.0) - solid-refresh@0.6.3(solid-js@1.8.19): + solid-refresh@0.6.3(solid-js@1.9.1): dependencies: '@babel/generator': 7.24.7 '@babel/helper-module-imports': 7.24.7 '@babel/types': 7.24.7 - solid-js: 1.8.19 + solid-js: 1.9.1 transitivePeerDependencies: - supports-color source-map-js@1.2.0: {} + source-map-js@1.2.1: {} + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 @@ -8759,25 +8803,13 @@ snapshots: source-map@0.7.4: {} + space-separated-tokens@2.0.2: {} + spawn-sync@1.0.15: dependencies: concat-stream: 1.6.2 os-shim: 0.1.3 - spdx-correct@3.2.0: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.13 - - spdx-exceptions@2.3.0: {} - - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.13 - - spdx-license-ids@3.0.13: {} - speakingurl@14.0.1: {} split@1.0.1: @@ -8786,8 +8818,6 @@ snapshots: stackback@0.0.2: {} - std-env@3.6.0: {} - std-env@3.7.0: {} stdin-discarder@0.1.0: @@ -8816,34 +8846,15 @@ snapshots: get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 - string.prototype.padend@3.1.4: - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - - string.prototype.trim@1.2.7: - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - - string.prototype.trimend@1.0.6: - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - - string.prototype.trimstart@1.0.6: - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -8852,16 +8863,12 @@ snapshots: dependencies: ansi-regex: 6.0.1 - strip-bom@3.0.0: {} - strip-bom@5.0.0: {} strip-final-newline@2.0.0: {} strip-final-newline@3.0.0: {} - strip-final-newline@4.0.0: {} - strip-json-comments@2.0.1: {} strip-json-comments@5.0.1: {} @@ -8899,7 +8906,7 @@ snapshots: '@ampproject/remapping': 2.3.0 '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 acorn: 8.12.1 aria-query: 5.3.0 axobject-query: 4.0.0 @@ -8919,7 +8926,7 @@ snapshots: css-tree: 2.3.1 css-what: 6.1.0 csso: 5.0.5 - picocolors: 1.0.1 + picocolors: 1.1.0 tabbable@6.2.0: {} @@ -8948,16 +8955,19 @@ snapshots: through@2.3.8: {} - tinybench@2.8.0: {} + tinybench@2.9.0: {} - tinypool@0.8.4: {} + tinyexec@0.3.0: {} + + tinyglobby@0.2.9: + dependencies: + fdir: 6.4.2(picomatch@4.0.2) + picomatch: 4.0.2 tinypool@1.0.0: {} tinyrainbow@1.2.0: {} - tinyspy@2.2.1: {} - tinyspy@3.0.0: {} titleize@3.0.0: {} @@ -8970,9 +8980,13 @@ snapshots: dependencies: is-number: 7.0.0 - ts-essentials@10.0.1(typescript@5.5.4): + totalist@3.0.1: {} + + trim-lines@3.0.1: {} + + ts-essentials@10.0.1(typescript@5.6.2): optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 tslib@2.6.0: {} @@ -8983,7 +8997,12 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - type-detect@4.1.0: {} + tsx@4.19.1: + dependencies: + esbuild: 0.23.0 + get-tsconfig: 4.7.5 + optionalDependencies: + fsevents: 2.3.3 type-fest@1.4.0: {} @@ -8991,54 +9010,39 @@ snapshots: type-fest@3.13.1: {} - type-fest@4.20.0: {} - - typed-array-length@1.0.4: - dependencies: - call-bind: 1.0.2 - for-each: 0.3.3 - is-typed-array: 1.1.10 - typedarray-to-buffer@3.1.5: dependencies: is-typedarray: 1.0.0 typedarray@0.0.6: {} - typedoc-plugin-markdown@4.0.0-next.23(typedoc@0.25.4(typescript@5.5.4)): + typedoc-plugin-markdown@4.0.0-next.23(typedoc@0.25.4(typescript@5.6.2)): dependencies: - typedoc: 0.25.4(typescript@5.5.4) + typedoc: 0.25.4(typescript@5.6.2) - typedoc-vitepress-theme@1.0.0-next.3(typedoc-plugin-markdown@4.0.0-next.23(typedoc@0.25.4(typescript@5.5.4))): + typedoc-vitepress-theme@1.0.0-next.3(typedoc-plugin-markdown@4.0.0-next.23(typedoc@0.25.4(typescript@5.6.2))): dependencies: - typedoc-plugin-markdown: 4.0.0-next.23(typedoc@0.25.4(typescript@5.5.4)) + typedoc-plugin-markdown: 4.0.0-next.23(typedoc@0.25.4(typescript@5.6.2)) - typedoc@0.25.4(typescript@5.5.4): + typedoc@0.25.4(typescript@5.6.2): dependencies: lunr: 2.3.9 marked: 4.3.0 minimatch: 9.0.3 shiki: 0.14.5 - typescript: 5.5.4 + typescript: 5.6.2 - typescript@5.5.4: {} + typescript@5.6.2: {} ua-parser-js@1.0.39: {} - ufo@1.4.0: {} - ufo@1.5.3: {} + ufo@1.5.4: {} + uhyphen@0.2.0: {} - unbox-primitive@1.0.2: - dependencies: - call-bind: 1.0.2 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - - unbuild@2.0.0(sass@1.77.8)(typescript@5.5.4): + unbuild@2.0.0(sass@1.79.4)(typescript@5.6.2): dependencies: '@rollup/plugin-alias': 5.1.0(rollup@3.29.4) '@rollup/plugin-commonjs': 25.0.8(rollup@3.29.4) @@ -9055,27 +9059,37 @@ snapshots: hookable: 5.5.3 jiti: 1.21.6 magic-string: 0.30.10 - mkdist: 1.5.4(sass@1.77.8)(typescript@5.5.4) + mkdist: 1.5.4(sass@1.79.4)(typescript@5.6.2) mlly: 1.7.1 pathe: 1.1.2 pkg-types: 1.1.3 pretty-bytes: 6.1.1 rollup: 3.29.4 - rollup-plugin-dts: 6.1.1(rollup@3.29.4)(typescript@5.5.4) + rollup-plugin-dts: 6.1.1(rollup@3.29.4)(typescript@5.6.2) scule: 1.3.0 untyped: 1.4.2 optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - sass - supports-color - vue-tsc + unconfig@0.5.5: + dependencies: + '@antfu/utils': 0.7.10 + defu: 6.1.4 + importx: 0.4.4 + transitivePeerDependencies: + - supports-color + undici-types@5.26.5: {} - unimport@3.11.1(rollup@4.19.0): + undici-types@6.19.8: {} + + unimport@3.13.1(rollup@4.24.0)(webpack-sources@3.2.3): dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.19.0) + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) acorn: 8.12.1 escape-string-regexp: 5.0.0 estree-walker: 3.0.3 @@ -9087,23 +9101,74 @@ snapshots: pkg-types: 1.2.0 scule: 1.3.0 strip-literal: 2.1.0 - unplugin: 1.12.3 + unplugin: 1.14.1(webpack-sources@3.2.3) transitivePeerDependencies: - rollup + - webpack-sources unique-string@3.0.0: dependencies: crypto-random-string: 4.0.0 + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.2 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.2 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.2 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + universalify@1.0.0: {} universalify@2.0.0: {} - unplugin@1.12.3: + unocss@0.63.4(postcss@8.4.47)(rollup@4.24.0)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)): + dependencies: + '@unocss/astro': 0.63.4(rollup@4.24.0)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) + '@unocss/cli': 0.63.4(rollup@4.24.0) + '@unocss/core': 0.63.4 + '@unocss/postcss': 0.63.4(postcss@8.4.47) + '@unocss/preset-attributify': 0.63.4 + '@unocss/preset-icons': 0.63.4 + '@unocss/preset-mini': 0.63.4 + '@unocss/preset-tagify': 0.63.4 + '@unocss/preset-typography': 0.63.4 + '@unocss/preset-uno': 0.63.4 + '@unocss/preset-web-fonts': 0.63.4 + '@unocss/preset-wind': 0.63.4 + '@unocss/transformer-attributify-jsx': 0.63.4 + '@unocss/transformer-compile-class': 0.63.4 + '@unocss/transformer-directives': 0.63.4 + '@unocss/transformer-variant-group': 0.63.4 + '@unocss/vite': 0.63.4(rollup@4.24.0)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) + optionalDependencies: + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + transitivePeerDependencies: + - postcss + - rollup + - supports-color + + unplugin@1.14.1(webpack-sources@3.2.3): dependencies: acorn: 8.12.1 - webpack-sources: 3.2.3 webpack-virtual-modules: 0.6.2 + optionalDependencies: + webpack-sources: 3.2.3 untildify@4.0.0: {} @@ -9123,7 +9188,13 @@ snapshots: dependencies: browserslist: 4.23.1 escalade: 3.1.2 - picocolors: 1.0.1 + picocolors: 1.1.0 + + update-browserslist-db@1.1.1(browserslist@4.24.0): + dependencies: + browserslist: 4.24.0 + escalade: 3.2.0 + picocolors: 1.1.0 update-notifier@6.0.2: dependencies: @@ -9148,92 +9219,80 @@ snapshots: validate-html-nesting@1.2.2: {} - validate-npm-package-license@3.0.4: + vfile-message@4.0.2: dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 - vite-node@1.6.0(@types/node@20.14.12)(sass@1.77.8): + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.2 + vfile-message: 4.0.2 + + vite-node@2.1.2(@types/node@20.16.10)(sass@1.79.4): dependencies: cac: 6.7.14 - debug: 4.3.5 + debug: 4.3.7 pathe: 1.1.2 - picocolors: 1.0.1 - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) transitivePeerDependencies: - '@types/node' - less - lightningcss - sass + - sass-embedded - stylus - sugarss - supports-color - terser - vite-node@2.0.4(@types/node@20.14.12)(sass@1.77.8): - dependencies: - cac: 6.7.14 - debug: 4.3.5 - pathe: 1.1.2 - tinyrainbow: 1.2.0 - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vite-plugin-solid@2.10.2(solid-js@1.8.19)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)): + vite-plugin-solid@2.10.2(solid-js@1.9.1)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)): dependencies: '@babel/core': 7.24.7 '@types/babel__core': 7.20.5 babel-preset-solid: 1.8.17(@babel/core@7.24.7) merge-anything: 5.1.7 - solid-js: 1.8.19 - solid-refresh: 0.6.3(solid-js@1.8.19) - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) - vitefu: 0.2.5(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)) + solid-js: 1.9.1 + solid-refresh: 0.6.3(solid-js@1.9.1) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + vitefu: 0.2.5(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) transitivePeerDependencies: - supports-color - vite@5.3.5(@types/node@20.14.12)(sass@1.77.8): + vite@5.4.8(@types/node@20.16.10)(sass@1.79.4): dependencies: esbuild: 0.21.5 - postcss: 8.4.39 - rollup: 4.19.0 + postcss: 8.4.47 + rollup: 4.24.0 optionalDependencies: - '@types/node': 20.14.12 + '@types/node': 20.16.10 fsevents: 2.3.3 - sass: 1.77.8 + sass: 1.79.4 - vitefu@0.2.5(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)): + vitefu@0.2.5(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)): optionalDependencies: - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) - vitepress@1.3.1(@algolia/client-search@4.20.0)(@types/node@20.14.12)(@types/react@18.3.3)(postcss@8.4.39)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)(search-insights@2.15.0)(typescript@5.5.4): + vitepress@1.3.4(@algolia/client-search@4.20.0)(@types/node@20.16.10)(@types/react@18.3.11)(postcss@8.4.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.4)(search-insights@2.15.0)(typescript@5.6.2): dependencies: - '@docsearch/css': 3.6.0 - '@docsearch/js': 3.6.0(@algolia/client-search@4.20.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.15.0) - '@shikijs/core': 1.10.3 - '@shikijs/transformers': 1.10.3 - '@types/markdown-it': 14.1.1 - '@vitejs/plugin-vue': 5.0.5(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8))(vue@3.4.34(typescript@5.5.4)) - '@vue/devtools-api': 7.3.6 - '@vue/shared': 3.4.31 - '@vueuse/core': 10.11.0(vue@3.4.34(typescript@5.5.4)) - '@vueuse/integrations': 10.11.0(focus-trap@7.5.4)(vue@3.4.34(typescript@5.5.4)) + '@docsearch/css': 3.6.2 + '@docsearch/js': 3.6.2(@algolia/client-search@4.20.0)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.15.0) + '@shikijs/core': 1.21.0 + '@shikijs/transformers': 1.21.0 + '@types/markdown-it': 14.1.2 + '@vitejs/plugin-vue': 5.1.4(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4))(vue@3.5.11(typescript@5.6.2)) + '@vue/devtools-api': 7.4.6 + '@vue/shared': 3.5.11 + '@vueuse/core': 11.1.0(vue@3.5.11(typescript@5.6.2)) + '@vueuse/integrations': 11.1.0(focus-trap@7.5.4)(vue@3.5.11(typescript@5.6.2)) focus-trap: 7.5.4 mark.js: 8.11.1 - minisearch: 7.0.2 - shiki: 1.10.3 - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) - vue: 3.4.34(typescript@5.5.4) + minisearch: 7.1.0 + shiki: 1.21.0 + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + vue: 3.5.11(typescript@5.6.2) optionalDependencies: - postcss: 8.4.39 + postcss: 8.4.47 transitivePeerDependencies: - '@algolia/client-search' - '@types/node' @@ -9253,6 +9312,7 @@ snapshots: - react - react-dom - sass + - sass-embedded - search-insights - sortablejs - stylus @@ -9261,78 +9321,46 @@ snapshots: - typescript - universal-cookie - vitest-mock-extended@2.0.0(typescript@5.5.4)(vitest@2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8)): + vitest-mock-extended@2.0.2(typescript@5.6.2)(vitest@2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4)): dependencies: - ts-essentials: 10.0.1(typescript@5.5.4) - typescript: 5.5.4 - vitest: 2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8) + ts-essentials: 10.0.1(typescript@5.6.2) + typescript: 5.6.2 + vitest: 2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4) - vitest-plugin-random-seed@1.1.0(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)): + vitest-plugin-random-seed@1.1.0(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)): dependencies: - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) - vitest@1.6.0(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8): + vitest@2.1.2(@types/node@20.16.10)(happy-dom@14.12.3)(sass@1.79.4): dependencies: - '@vitest/expect': 1.6.0 - '@vitest/runner': 1.6.0 - '@vitest/snapshot': 1.6.0 - '@vitest/spy': 1.6.0 - '@vitest/utils': 1.6.0 - acorn-walk: 8.3.3 - chai: 4.5.0 - debug: 4.3.5 - execa: 8.0.1 - local-pkg: 0.5.0 - magic-string: 0.30.10 - pathe: 1.1.2 - picocolors: 1.0.1 - std-env: 3.7.0 - strip-literal: 2.1.0 - tinybench: 2.8.0 - tinypool: 0.8.4 - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) - vite-node: 1.6.0(@types/node@20.14.12)(sass@1.77.8) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 20.14.12 - happy-dom: 14.12.3 - transitivePeerDependencies: - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vitest@2.0.4(@types/node@20.14.12)(happy-dom@14.12.3)(sass@1.77.8): - dependencies: - '@ampproject/remapping': 2.3.0 - '@vitest/expect': 2.0.4 - '@vitest/pretty-format': 2.0.4 - '@vitest/runner': 2.0.4 - '@vitest/snapshot': 2.0.4 - '@vitest/spy': 2.0.4 - '@vitest/utils': 2.0.4 + '@vitest/expect': 2.1.2 + '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.4)) + '@vitest/pretty-format': 2.1.2 + '@vitest/runner': 2.1.2 + '@vitest/snapshot': 2.1.2 + '@vitest/spy': 2.1.2 + '@vitest/utils': 2.1.2 chai: 5.1.1 - debug: 4.3.5 - execa: 8.0.1 - magic-string: 0.30.10 + debug: 4.3.7 + magic-string: 0.30.11 pathe: 1.1.2 std-env: 3.7.0 - tinybench: 2.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.0 tinypool: 1.0.0 tinyrainbow: 1.2.0 - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8) - vite-node: 2.0.4(@types/node@20.14.12)(sass@1.77.8) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.4) + vite-node: 2.1.2(@types/node@20.16.10)(sass@1.79.4) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 20.14.12 + '@types/node': 20.16.10 happy-dom: 14.12.3 transitivePeerDependencies: - less - lightningcss + - msw - sass + - sass-embedded - stylus - sugarss - supports-color @@ -9342,19 +9370,19 @@ snapshots: vscode-textmate@8.0.0: {} - vue-demi@0.14.8(vue@3.4.34(typescript@5.5.4)): + vue-demi@0.14.10(vue@3.5.11(typescript@5.6.2)): dependencies: - vue: 3.4.34(typescript@5.5.4) + vue: 3.5.11(typescript@5.6.2) - vue@3.4.34(typescript@5.5.4): + vue@3.5.11(typescript@5.6.2): dependencies: - '@vue/compiler-dom': 3.4.34 - '@vue/compiler-sfc': 3.4.34 - '@vue/runtime-dom': 3.4.34 - '@vue/server-renderer': 3.4.34(vue@3.4.34(typescript@5.5.4)) - '@vue/shared': 3.4.34 + '@vue/compiler-dom': 3.5.11 + '@vue/compiler-sfc': 3.5.11 + '@vue/runtime-dom': 3.5.11 + '@vue/server-renderer': 3.5.11(vue@3.5.11(typescript@5.6.2)) + '@vue/shared': 3.5.11 optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 watchpack@2.4.1: dependencies: @@ -9400,7 +9428,8 @@ snapshots: webidl-conversions@7.0.0: {} - webpack-sources@3.2.3: {} + webpack-sources@3.2.3: + optional: true webpack-virtual-modules@0.6.2: {} @@ -9408,32 +9437,11 @@ snapshots: when@3.7.7: {} - which-boxed-primitive@1.0.2: - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - - which-typed-array@1.1.9: - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - is-typed-array: 1.1.10 - which@1.2.4: dependencies: is-absolute: 0.1.7 isexe: 1.1.2 - which@1.3.1: - dependencies: - isexe: 2.0.0 - which@2.0.2: dependencies: isexe: 2.0.0 @@ -9493,9 +9501,7 @@ snapshots: yallist@4.0.0: {} - yaml@2.4.5: {} - - yaml@2.5.0: {} + yaml@2.5.1: {} yargs-parser@20.2.9: {} @@ -9504,7 +9510,7 @@ snapshots: yargs@16.2.0: dependencies: cliui: 7.0.4 - escalade: 3.1.1 + escalade: 3.1.2 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 @@ -9526,13 +9532,11 @@ snapshots: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 - yocto-queue@1.1.1: {} - - yoctocolors@2.0.2: {} - zip-dir@2.0.0: dependencies: async: 3.2.4 jszip: 3.10.1 zod@3.22.4: {} + + zwitch@2.0.4: {} diff --git a/scripts/bump-package-version.ts b/scripts/bump-package-version.ts index 86d5603e..83863653 100644 --- a/scripts/bump-package-version.ts +++ b/scripts/bump-package-version.ts @@ -5,7 +5,7 @@ import { generateMarkDown, parseChangelogMarkdown, } from 'changelogen'; -import { execa } from 'execa'; +import spawn from 'nano-spawn'; import { getPkgTag, grabPackageDetails, listCommitsInDir } from './git'; import { consola } from 'consola'; import fs from 'fs-extra'; @@ -36,7 +36,7 @@ if (currentVersion.startsWith('0.')) { bumpType = 'patch'; } } -await execa('pnpm', ['version', bumpType], { +await spawn('pnpm', ['version', bumpType], { cwd: pkgDir, }); const updatedPkgJson = await fs.readJson(pkgJsonPath); @@ -82,11 +82,11 @@ await fs.writeFile(changelogPath, newChangelog, 'utf8'); consola.success('Updated changelog'); // Commit changes -await execa('git', ['add', pkgJsonPath, changelogPath]); -await execa('git', [ +await spawn('git', ['add', pkgJsonPath, changelogPath]); +await spawn('git', [ 'commit', '-m', `chore(release): ${pkgName} v${newVersion}`, ]); -await execa('git', ['tag', newTag]); +await spawn('git', ['tag', newTag]); consola.success('Committed version and changelog'); diff --git a/scripts/generate-readmes.sh b/scripts/generate-readmes.sh new file mode 100755 index 00000000..fc8b4f1e --- /dev/null +++ b/scripts/generate-readmes.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# +# Generate code in README.md and sync it with wxt/packages/README.md for NPM +# + +pnpm dlx automd +echo "" > packages/wxt/README.md +cat README.md >> packages/wxt/README.md diff --git a/taze.config.ts b/taze.config.ts index 0d2a1f84..0bc140cf 100644 --- a/taze.config.ts +++ b/taze.config.ts @@ -1,4 +1,11 @@ // https://github.com/antfu-collective/taze?tab=readme-ov-file#config-file export default { - exclude: ['typedoc', 'typedoc-plugin-markdown', 'typedoc-vitepress-theme'], + exclude: [ + // Very touchy, don't change: + 'typedoc', + 'typedoc-plugin-markdown', + 'typedoc-vitepress-theme', + // Manually manage version so a single version is used: + 'esbuild', + ], }; diff --git a/templates/react/package.json b/templates/react/package.json index c92fbb3a..1b702c13 100644 --- a/templates/react/package.json +++ b/templates/react/package.json @@ -19,10 +19,10 @@ "react-dom": "^18.3.1" }, "devDependencies": { - "@types/react": "^18.3.3", + "@types/react": "^18.3.11", "@types/react-dom": "^18.3.0", - "@wxt-dev/module-react": "^1.1.0", - "typescript": "^5.5.4", - "wxt": "^0.19.1" + "@wxt-dev/module-react": "^1.1.1", + "typescript": "^5.6.2", + "wxt": "^0.19.11" } } diff --git a/templates/react/wxt.config.ts b/templates/react/wxt.config.ts index 429f2b90..d1e35387 100644 --- a/templates/react/wxt.config.ts +++ b/templates/react/wxt.config.ts @@ -2,5 +2,6 @@ import { defineConfig } from 'wxt'; // See https://wxt.dev/api/config.html export default defineConfig({ + extensionApi: 'chrome', modules: ['@wxt-dev/module-react'], }); diff --git a/templates/solid/package.json b/templates/solid/package.json index 8944899e..9115717c 100644 --- a/templates/solid/package.json +++ b/templates/solid/package.json @@ -15,11 +15,11 @@ "postinstall": "wxt prepare" }, "dependencies": { - "solid-js": "^1.8.19" + "solid-js": "^1.9.1" }, "devDependencies": { - "@wxt-dev/module-solid": "^1.1.1", - "typescript": "^5.5.4", - "wxt": "^0.19.1" + "@wxt-dev/module-solid": "^1.1.2", + "typescript": "^5.6.2", + "wxt": "^0.19.11" } } diff --git a/templates/solid/wxt.config.ts b/templates/solid/wxt.config.ts index 1cc7596d..0a5a994f 100644 --- a/templates/solid/wxt.config.ts +++ b/templates/solid/wxt.config.ts @@ -2,5 +2,6 @@ import { defineConfig } from 'wxt'; // See https://wxt.dev/api/config.html export default defineConfig({ + extensionApi: 'chrome', modules: ['@wxt-dev/module-solid'], }); diff --git a/templates/svelte/package.json b/templates/svelte/package.json index 3736a5dc..bdad117b 100644 --- a/templates/svelte/package.json +++ b/templates/svelte/package.json @@ -16,11 +16,11 @@ }, "devDependencies": { "@tsconfig/svelte": "^5.0.4", - "@wxt-dev/module-svelte": "^1.0.0", - "svelte": "^4.2.18", - "svelte-check": "^3.8.4", - "tslib": "^2.6.3", - "typescript": "^5.5.4", - "wxt": "^0.19.1" + "@wxt-dev/module-svelte": "^1.0.1", + "svelte": "^4.2.19", + "svelte-check": "^3.8.6", + "tslib": "^2.7.0", + "typescript": "^5.6.2", + "wxt": "^0.19.11" } } diff --git a/templates/svelte/wxt.config.ts b/templates/svelte/wxt.config.ts index 5749b4e6..f0e4f9aa 100644 --- a/templates/svelte/wxt.config.ts +++ b/templates/svelte/wxt.config.ts @@ -3,5 +3,6 @@ import { defineConfig } from 'wxt'; // See https://wxt.dev/api/config.html export default defineConfig({ srcDir: 'src', + extensionApi: 'chrome', modules: ['@wxt-dev/module-svelte'], }); diff --git a/templates/vanilla/package.json b/templates/vanilla/package.json index e547a13a..a5bc9d58 100644 --- a/templates/vanilla/package.json +++ b/templates/vanilla/package.json @@ -15,7 +15,7 @@ "postinstall": "wxt prepare" }, "devDependencies": { - "typescript": "^5.5.4", - "wxt": "^0.19.1" + "typescript": "^5.6.2", + "wxt": "^0.19.11" } } diff --git a/templates/vanilla/wxt.config.ts b/templates/vanilla/wxt.config.ts index 1e2f53d3..35c7ade7 100644 --- a/templates/vanilla/wxt.config.ts +++ b/templates/vanilla/wxt.config.ts @@ -1,4 +1,6 @@ import { defineConfig } from 'wxt'; // See https://wxt.dev/api/config.html -export default defineConfig({}); +export default defineConfig({ + extensionApi: 'chrome', +}); diff --git a/templates/vue/package.json b/templates/vue/package.json index 15b71575..eff1642f 100644 --- a/templates/vue/package.json +++ b/templates/vue/package.json @@ -15,12 +15,12 @@ "postinstall": "wxt prepare" }, "dependencies": { - "vue": "^3.4.34" + "vue": "^3.5.11" }, "devDependencies": { - "@wxt-dev/module-vue": "^1.0.0", - "typescript": "^5.5.4", - "vue-tsc": "^2.0.29", - "wxt": "^0.19.1" + "@wxt-dev/module-vue": "^1.0.1", + "typescript": "^5.6.2", + "vue-tsc": "^2.1.6", + "wxt": "^0.19.11" } } diff --git a/templates/vue/wxt.config.ts b/templates/vue/wxt.config.ts index 55fbc4af..2ab714b1 100644 --- a/templates/vue/wxt.config.ts +++ b/templates/vue/wxt.config.ts @@ -2,5 +2,6 @@ import { defineConfig } from 'wxt'; // See https://wxt.dev/api/config.html export default defineConfig({ + extensionApi: 'chrome', modules: ['@wxt-dev/module-vue'], }); diff --git a/tsconfig.base.json b/tsconfig.base.json index 1dbd78cf..78d6cbc9 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -11,9 +11,6 @@ "strict": true, "lib": ["DOM", "WebWorker", "ESNext"], - /* Linting */ - "noUnusedLocals": true, - /* Completeness */ "skipLibCheck": true }
  • Input PatternFilename Output Path
    + entrypoints/{{ pattern[0] }} @@ -31,7 +31,7 @@ const props = defineProps<{ /> + /{{ pattern[1] }}