Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d8a8202e63 | |||
| c9eb3b0ca9 | |||
| 665f5a52c4 | |||
| 798f3b8e47 | |||
| a886ab28e1 | |||
| 28cff9c90a | |||
| 8ce197b023 | |||
| a5553457c6 | |||
| 7d9ed777fb | |||
| 59362e7274 | |||
| d32d17952c | |||
| 6630bca73f | |||
| befd442075 | |||
| da885ff6c8 | |||
| 349b216439 | |||
| 47b78d66cf | |||
| fe2baef2b1 | |||
| 357bbdaec9 | |||
| a38e3c2733 | |||
| f17e527d72 | |||
| e20de4ca0d | |||
| 16ac53e0a1 | |||
| fee978bf25 | |||
| f80909d63e | |||
| d5b2503155 | |||
| 80ca5760e2 | |||
| 44dab3726f | |||
| c4295a4f4b | |||
| a6a91250d1 | |||
| 1db50ed7a9 | |||
| 342057b3f5 | |||
| 151b1392c6 | |||
| 1d5d0663ac | |||
| 30b8ba495d | |||
| 5775c9ce0f | |||
| 4f82dd87fc | |||
| fab9fa81d1 | |||
| d6ee4560d8 | |||
| 655ba863a0 | |||
| ac92d4019f | |||
| 0ff964a04b | |||
| 89459f0a4d | |||
| 0d56100abb | |||
| dc770b5952 | |||
| 8cd2bff67a | |||
| 11e55e2499 | |||
| 4cab3a5593 | |||
| daa0eed851 | |||
| 868a347d40 | |||
| 48a87aa352 | |||
| dfec8a3608 | |||
| 9a71231436 | |||
| db4592fbb3 | |||
| 8551d6071e | |||
| c40285f750 | |||
| 9238f9fd85 | |||
| ba3d8838e3 | |||
| e9b6f5f97c | |||
| 5b6c82d38f | |||
| 5b41b70abe | |||
| 93f624610f | |||
| 73bdd49471 | |||
| 635f3f0898 | |||
| a53ee6d590 | |||
| 665b9194cf | |||
| 4690418c94 | |||
| 20eea2a7d1 | |||
| ac7b6760f2 | |||
| a593cfbbb6 | |||
| a205f2a0a8 | |||
| 8e2badc92b | |||
| 7c18d9c0b8 | |||
| 55a1f39450 | |||
| d708eca78e | |||
| 5d7e2516b6 | |||
| fb6a29872b | |||
| 187206062e | |||
| 2615e29e52 | |||
| 8ca176d37e | |||
| cb2bf43f30 | |||
| 1719d17cff | |||
| 32afb8d97c | |||
| 72b8a29d76 | |||
| af0a32d478 | |||
| 060e85f90e | |||
| 654a54ac79 | |||
| ef24358942 | |||
| e5e67e39bd | |||
| 228304bef9 |
@@ -0,0 +1,10 @@
|
||||
extends:
|
||||
- '@commitlint/config-conventional'
|
||||
rules:
|
||||
subject-case:
|
||||
- 0
|
||||
- always
|
||||
- - sentence-case
|
||||
- start-case
|
||||
- pascal-case
|
||||
- upper-case
|
||||
@@ -1,5 +1,13 @@
|
||||
# See https://git-scm.com/docs/gitattributes#_pattern_format for more about `.gitattributes`.
|
||||
|
||||
# Normalize EOL for all files that Git considers text files
|
||||
* text=auto eol=lf
|
||||
|
||||
# Mark lock files as generated to avoid diffing
|
||||
pnpm-lock.yaml linguist-generated
|
||||
package-lock.json linguist-generated
|
||||
bun.lockb linguist-generated
|
||||
yarn.lock linguist-generated
|
||||
|
||||
# Exclude templates from language statistics
|
||||
templates/**/* linguist-vendored
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Set default
|
||||
* @aklinker1 @Timeraa
|
||||
|
||||
# Secure Directories
|
||||
/.github/ @aklinker1
|
||||
|
||||
# Creator of specific wxt modules
|
||||
/packages/auto-icons/ @Timeraa
|
||||
/packages/unocss/ @Timeraa
|
||||
+2
-14
@@ -1,15 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository#about-funding-files
|
||||
|
||||
github: [wxt-dev] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||
thanks_dev: # Replace with a single thanks.dev username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
github: wxt-dev
|
||||
|
||||
@@ -1,23 +1,31 @@
|
||||
name: Basic Setup
|
||||
description: Install PNPM, Node, and dependencies
|
||||
|
||||
inputs:
|
||||
install:
|
||||
default: 'true'
|
||||
type: boolean
|
||||
description: Whether or not to run 'pnpm install'
|
||||
|
||||
installArgs:
|
||||
default: ''
|
||||
type: string
|
||||
description: Additional args to append to "pnpm install"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Setup PNPM
|
||||
- name: 🛠️ Setup PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
- name: Setup NodeJS
|
||||
|
||||
- name: 🛠️ Setup NodeJS
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: pnpm
|
||||
- name: Install Dependencies
|
||||
|
||||
- name: 📦 Install Dependencies
|
||||
if: ${{ inputs.install == 'true' }}
|
||||
shell: bash
|
||||
run: pnpm install ${{ inputs.installArgs }}
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directories:
|
||||
- /
|
||||
- packages/*
|
||||
directory: /
|
||||
schedule:
|
||||
interval: 'monthly'
|
||||
- package-ecosystem: 'github-actions'
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
### Overview
|
||||
|
||||
<!-- Describe your changes and why you made them -->
|
||||
|
||||
### Manual Testing
|
||||
|
||||
<!-- Describe how to test your changes to make sure the PR works as intended -->
|
||||
|
||||
### Related Issue
|
||||
|
||||
<!-- If this PR is related to an issue, please link it here -->
|
||||
|
||||
This PR closes #<issue_number>
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Continuous Publish
|
||||
name: ✨ pkg.pr.new
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -7,11 +7,22 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Publish Test Packages
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm buildc all
|
||||
- run: pnpx pkg-pr-new publish --compact './packages/*'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build All Packages
|
||||
run: pnpm buildc all
|
||||
|
||||
- name: Publish
|
||||
run: pnpx pkg-pr-new publish --compact --pnpm './packages/*'
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
name: 🎉 PR closed
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
thank-you:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.merged == true
|
||||
|
||||
steps:
|
||||
- name: Post Thank You Comment
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
env:
|
||||
comment: Thanks for helping make WXT better!
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: process.env.comment
|
||||
})
|
||||
@@ -0,0 +1,26 @@
|
||||
name: 🛡️ Check PR Title
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited]
|
||||
|
||||
jobs:
|
||||
lint-pr-title:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
# Only fetch the config file from the repository
|
||||
sparse-checkout-cone-mode: false
|
||||
sparse-checkout: .commitlintrc.yml
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --global @commitlint/config-conventional commitlint
|
||||
|
||||
- name: Check PR title with commitlint
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
HELP_URL: https://github.com/wxt-dev/wxt/blob/main/CONTRIBUTING.md#conventional-pr-titles
|
||||
run: echo "$PR_TITLE" | npx commitlint --help-url $HELP_URL
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Publish Docs
|
||||
name: 📝 Publish Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -10,20 +10,38 @@ on:
|
||||
required: true
|
||||
default: latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
# Only run if it's the upstream repository, not forks
|
||||
if: github.repository == 'wxt-dev/wxt'
|
||||
name: Publish Docs
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: docker/login-action@v3
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: https://${{ secrets.DOCKER_REGISTRY_HOSTNAME }}
|
||||
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
|
||||
- run: pnpm docs:build
|
||||
- run: docker build docs/.vitepress -t ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
|
||||
- run: docker push ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
|
||||
- run: curl -X POST -i ${{ secrets.UPDATE_DOCS_WEBHOOK }}
|
||||
|
||||
- name: Build docs
|
||||
run: |
|
||||
pnpm docs:build
|
||||
docker build docs/.vitepress -t ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
|
||||
|
||||
- name: Push Image
|
||||
run: docker push ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
|
||||
|
||||
- name: Deploy
|
||||
run: curl -X POST -i ${{ secrets.UPDATE_DOCS_WEBHOOK }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Release
|
||||
name: 🚀 Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -17,38 +17,51 @@ on:
|
||||
- unocss
|
||||
- wxt
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
name: Validate
|
||||
uses: './.github/workflows/validate.yml'
|
||||
secrets: inherit
|
||||
|
||||
publish:
|
||||
name: Publish
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: write
|
||||
needs:
|
||||
- validate
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: ./.github/actions/setup
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.name 'github-actions[bot]'
|
||||
git config user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
git config --global push.followTags true
|
||||
|
||||
- name: Bump and Tag
|
||||
run: |
|
||||
git config user.email "github-actions@users.noreply.github.com"
|
||||
git config user.name "GitHub Actions"
|
||||
pnpm tsx scripts/bump-package-version.ts ${{ inputs.package }}
|
||||
git push
|
||||
git push --tags
|
||||
|
||||
- name: NPM
|
||||
- name: Publish to NPM
|
||||
working-directory: packages/${{ inputs.package }}
|
||||
run: |
|
||||
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}" > ~/.npmrc
|
||||
pnpm build
|
||||
pnpm publish
|
||||
working-directory: packages/${{ inputs.package }}
|
||||
|
||||
- name: GitHub Release
|
||||
- name: Create GitHub release
|
||||
run: pnpm tsx scripts/create-github-release.ts ${{ inputs.package }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Sync Releases
|
||||
name: 🔄 Sync Releases
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -16,14 +16,25 @@ on:
|
||||
- storage
|
||||
- wxt
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: Sync Releases
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
installArgs: --ignore-scripts
|
||||
- run: pnpm tsx scripts/sync-releases.ts ${{ inputs.package }}
|
||||
|
||||
- name: Sync Releases
|
||||
run: pnpm tsx scripts/sync-releases.ts ${{ inputs.package }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Validate
|
||||
name: 🛡️ Validate
|
||||
on:
|
||||
workflow_call:
|
||||
pull_request:
|
||||
@@ -6,46 +6,90 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
checks:
|
||||
name: Checks
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm check
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Basic Checks
|
||||
run: pnpm check
|
||||
|
||||
builds:
|
||||
name: Builds
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm buildc all
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build All Packages
|
||||
run: pnpm buildc all
|
||||
|
||||
build-demo:
|
||||
name: Build Demo
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm build:all
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Build
|
||||
run: pnpm build:all
|
||||
working-directory: packages/wxt-demo
|
||||
- run: pnpm wxt zip
|
||||
|
||||
- name: ZIP
|
||||
run: pnpm wxt zip
|
||||
working-directory: packages/wxt-demo
|
||||
|
||||
tests:
|
||||
name: Tests
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- name: pnpm test:coverage
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Run Tests
|
||||
run: pnpm test:coverage -- --reporter=default --reporter=hanging-process
|
||||
- uses: codecov/codecov-action@v5
|
||||
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
windows-tests:
|
||||
name: Windows Tests
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm test
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Run Tests
|
||||
run: pnpm test
|
||||
|
||||
template:
|
||||
name: Template
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -57,19 +101,34 @@ jobs:
|
||||
- vanilla
|
||||
- vue
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm pack
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Pack WXT package
|
||||
run: pnpm pack
|
||||
working-directory: packages/wxt
|
||||
- run: npm i
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm i
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
- run: npm i -D ../../packages/wxt/wxt-*.tgz
|
||||
|
||||
- name: Install Packed WXT
|
||||
run: npm i -D ../../packages/wxt/wxt-*.tgz
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
- run: pnpm compile
|
||||
|
||||
- name: Type Check Template
|
||||
run: pnpm compile
|
||||
if: matrix.template != 'svelte'
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
- run: pnpm check
|
||||
|
||||
- name: Type Check Template
|
||||
run: pnpm check
|
||||
if: matrix.template == 'svelte'
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
- run: pnpm build
|
||||
|
||||
- name: Build Template
|
||||
run: pnpm build
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
|
||||
@@ -1,26 +1,41 @@
|
||||
name: vhs
|
||||
name: 📼 VHS
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'docs/tapes/*.tape'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
vhs:
|
||||
name: Create VHS
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
install: 'false'
|
||||
- name: Preinstall WXT
|
||||
install: false
|
||||
|
||||
# This prevents pnpm dlx from downloading WXT in the video
|
||||
- name: Pre-install WXT
|
||||
run: |
|
||||
pnpm store add wxt@latest
|
||||
pnpm dlx wxt@latest --version
|
||||
- uses: charmbracelet/vhs-action@v2.1.0
|
||||
|
||||
- name: Record VHS
|
||||
uses: charmbracelet/vhs-action@v2.1.0
|
||||
with:
|
||||
path: 'docs/tapes/init-demo.tape'
|
||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
||||
|
||||
- name: Save recorded GIF
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
.webextrc
|
||||
.wxt
|
||||
*.log
|
||||
/.vscode/
|
||||
/docs/.vitepress/cache
|
||||
coverage
|
||||
dist
|
||||
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"davidanson.vscode-markdownlint",
|
||||
"esbenp.prettier-vscode",
|
||||
"github.vscode-github-actions"
|
||||
]
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
// Set default formatter
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
|
||||
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
||||
"[yaml]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
||||
"[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
||||
"[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
|
||||
|
||||
// Additional guidelines for Copilot
|
||||
"github.copilot.chat.codeGeneration.instructions": [
|
||||
{ "file": "CONTRIBUTING.md" }
|
||||
]
|
||||
}
|
||||
+10
-2
@@ -8,9 +8,17 @@ If you want to add a new feature, please create an issue or discussion first so
|
||||
|
||||
## Conventional Commits
|
||||
|
||||
This project uses [Conventional Commits](https://www.conventionalcommits.org/en) to automate versioning. If you're a new contributor, don't worry about this. When you open a PR, a maintainer will change the PR's title so it's in the style of conventional commits, but that's all.
|
||||
This project uses [Conventional Commit format](https://www.conventionalcommits.org/en/v1.0.0/) to automatically generate a changelog and better understand the changes in the project
|
||||
|
||||
Maintainers, commits to the `main` branch (either directly or via PRs) must be valid conventional commits.
|
||||
Here are some examples of conventional commit messages:
|
||||
|
||||
- `feat: add new functionality`
|
||||
- `fix: correct typos in code`
|
||||
- `ci: add GitHub Actions for automated testing`
|
||||
|
||||
## Conventional PR Titles
|
||||
|
||||
The title of your pull request should follow the [conventional commit format](#conventional-commits). When a pull request is merged to the main branch, all changes are going to be squashed into a single commit. The message of this commit will be the title of the pull request. And for every release, the commit messages are used to generate the changelog.
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Security Policy
|
||||
|
||||
While WXT is in prerelease, only the latest version will receive security updates. The latest version is:
|
||||
|
||||
<img alt="npm version" src="https://img.shields.io/npm/v/wxt?labelColor=black&color=%234fa048">
|
||||
|
||||
<!--
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Use this section to tell people how to report a vulnerability.
|
||||
|
||||
Tell them where to go, how often they can expect to get an update on a
|
||||
reported vulnerability, what to expect if the vulnerability is accepted or
|
||||
declined, etc.
|
||||
-->
|
||||
@@ -62,6 +62,12 @@ const chromeExtensionIds = [
|
||||
'hjjkgbibknbahijglkffklflidncplkn', // Show IP – Live View of Website IPs for Developers
|
||||
'ilbikcehnpkmldojkcmlldkoelofnbde', // Strong Password Generator
|
||||
'ocllfkhcdopiafndigclebelbecaiocp', // ZenGram: Mindful Instagram, Your Way
|
||||
'odffpjnpocjfcaclnenaaaddghkgijdb', // Blync: Preview Links, Selection Search, AI Assistant
|
||||
'kofbbilhmnkcmibjbioafflgmpkbnmme', // HTML to Markdown - Convert webpages to markdown
|
||||
'boecmgggeigllcdocgioijmleimjbfkg', // Walmart WFS Profit Calculator
|
||||
'dlnjcbkmomenmieechnmgglgcljhoepd', // Youtube Live Chat Fullscreen
|
||||
'keiealdacakpnbbljlmhfgcebmaadieg', // Python Code Runner
|
||||
'hafcajcllbjnoolpfngclfmmgpikdhlm', // Monochromate
|
||||
];
|
||||
|
||||
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
|
||||
|
||||
@@ -14,6 +14,7 @@ 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';
|
||||
import { version as storageVersion } from '../../packages/storage/package.json';
|
||||
import knowledge from 'vitepress-knowledge';
|
||||
|
||||
const title = 'Next-gen Web Extension Framework';
|
||||
const titleSuffix = ' – WXT';
|
||||
@@ -25,6 +26,17 @@ const ogImage = 'https://wxt.dev/social-preview.png';
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
extends: knowledge({
|
||||
serverUrl: 'https://knowledge.wxt.dev',
|
||||
paths: {
|
||||
'/': 'docs',
|
||||
'/api/': 'api-reference',
|
||||
},
|
||||
pageSelectors: {
|
||||
'examples.md': '#VPContent > .VPPage',
|
||||
},
|
||||
}),
|
||||
|
||||
titleTemplate: `:title${titleSuffix}`,
|
||||
title: 'WXT',
|
||||
description,
|
||||
@@ -152,6 +164,7 @@ export default defineConfig({
|
||||
menuGroup('Resources', '/guide/resources/', [
|
||||
menuItem('Compare', 'compare.md'),
|
||||
menuItem('FAQ', 'faq.md'),
|
||||
menuItem('Community', 'community.md'),
|
||||
menuItem('Upgrading WXT', 'upgrading.md'),
|
||||
menuItem('Migrate to WXT', 'migrate.md'),
|
||||
menuItem('How WXT Works', 'how-wxt-works.md'),
|
||||
|
||||
@@ -28,13 +28,13 @@ export function menuRoot(items: SidebarItem[]) {
|
||||
export function menuGroup(
|
||||
text: string,
|
||||
items: SidebarItem[],
|
||||
collapsable?: boolean,
|
||||
collapsible?: boolean,
|
||||
): SidebarItem;
|
||||
export function menuGroup(
|
||||
text: string,
|
||||
base: string,
|
||||
items: SidebarItem[],
|
||||
collapsable?: boolean,
|
||||
collapsible?: boolean,
|
||||
): SidebarItem;
|
||||
export function menuGroup(
|
||||
text: string,
|
||||
|
||||
@@ -16,7 +16,8 @@ img.src = imageUrl;
|
||||
```
|
||||
|
||||
```html [HTML]
|
||||
<img src="~/assets/image.png" />
|
||||
<!-- In HTML tags, you must use the relative path --->
|
||||
<img src="../assets/image.png" />
|
||||
```
|
||||
|
||||
```css [CSS]
|
||||
@@ -25,6 +26,22 @@ img.src = imageUrl;
|
||||
}
|
||||
```
|
||||
|
||||
```vue [Vue]
|
||||
<script>
|
||||
import image from '~/assets/image.png';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img :src="image" />
|
||||
</template>
|
||||
```
|
||||
|
||||
```jsx [JSX]
|
||||
import image from '~/assets/image.png';
|
||||
|
||||
<img src={image} />;
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## `/public` Directory
|
||||
@@ -52,6 +69,16 @@ img.src = imageUrl;
|
||||
}
|
||||
```
|
||||
|
||||
```vue [Vue]
|
||||
<template>
|
||||
<img src="/image.png" />
|
||||
</template>
|
||||
```
|
||||
|
||||
```jsx [JSX]
|
||||
<img src="/image.png" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Inside Content Scripts
|
||||
@@ -114,7 +141,7 @@ export default defineConfig({
|
||||
manifest: {
|
||||
web_accessible_resources: [
|
||||
{
|
||||
// We'll use this matches in the cotent script as well
|
||||
// We'll use this matches in the content script as well
|
||||
matches: ['*://*.github.com/*'],
|
||||
// Use the same path as `relativeDest` from the WXT module
|
||||
resources: ['/oxc_parser_wasm_bg.wasm'],
|
||||
|
||||
@@ -11,7 +11,7 @@ export default defineConfig({
|
||||
});
|
||||
```
|
||||
|
||||
By default, WXT automatically setups up auto-imports for all of it's own APIs:
|
||||
By default, WXT sets up auto-imports for all of it's own APIs:
|
||||
|
||||
- [`browser`](/api/reference/wxt/browser/variables/browser) from `wxt/browser`
|
||||
- [`defineContentScript`](/api/reference/wxt/sandbox/functions/defineContentScript) from `wxt/sandbox`
|
||||
|
||||
@@ -6,7 +6,7 @@ outline: deep
|
||||
|
||||
> 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.
|
||||
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
|
||||
|
||||
@@ -41,6 +41,8 @@ export default defineRunnerConfig({
|
||||
});
|
||||
```
|
||||
|
||||
By default, WXT will try to automatically discover where Chrome/Firefox are installed. However, if you have chrome installed in a non-standard location, you need to set it manually as shown above.
|
||||
|
||||
### 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.
|
||||
@@ -72,7 +74,7 @@ export default defineRunnerConfig({
|
||||
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.
|
||||
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 your user's home directory.
|
||||
:::
|
||||
|
||||
### Disable Opening Browser
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
# 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.
|
||||
In WXT, there is no `manifest.json` file in your source code. Instead, WXT generates the manifest from multiple sources:
|
||||
|
||||
## Manifest Config
|
||||
- Global options [defined in your `wxt.config.ts` file](#global-options)
|
||||
- Entrypoint-specific options [defined in your entrypoints](/guide/essentials/entrypoints#defining-manifest-options)
|
||||
- [WXT Modules](/guide/essentials/wxt-modules) added to your project can modify your manifest
|
||||
- [Hooks](/guide/essentials/config/hooks) defined in your project can modify your manifest
|
||||
|
||||
To manually add a property to the `manifest.json` output during builds, use the `manifest` config inside `wxt.config.ts`:
|
||||
Your extension's `manifest.json` will be output to `.output/{target}/manifest.json` when running `wxt build`.
|
||||
|
||||
## Global Options
|
||||
|
||||
To add a property to your manifest, use the `manifest` config inside your `wxt.config.ts`:
|
||||
|
||||
```ts
|
||||
export default defineConfig({
|
||||
@@ -130,7 +137,7 @@ public/
|
||||
└─ icon-128.png
|
||||
```
|
||||
|
||||
Specifically, if an icon must match one of these regex to be discovered:
|
||||
Specifically, an icon must match one of these regex to be discovered:
|
||||
|
||||
<<< @/../packages/wxt/src/core/utils/manifest.ts#snippet
|
||||
|
||||
@@ -216,22 +223,7 @@ By default, whenever an `action` is generated, WXT falls back to `browser_action
|
||||
|
||||
### 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:
|
||||
To generate a manifest where a UI appears after clicking the icon, just create a [Popup entrypoint](/guide/essentials/entrypoints#popup). If you want to use a `page_action` for MV2, add the following meta tag to the HTML document's head:
|
||||
|
||||
```html
|
||||
<meta name="manifest.type" content="page_action" />
|
||||
|
||||
@@ -14,7 +14,7 @@ At a minimum, you need to create a TSConfig in your root directory that looks li
|
||||
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
|
||||
/// <reference types="./.wxt/wxt.d.ts" />
|
||||
/// <reference path="./.wxt/wxt.d.ts" />
|
||||
```
|
||||
|
||||
## Compiler Options
|
||||
|
||||
@@ -4,12 +4,14 @@ outline: deep
|
||||
|
||||
# Content Scripts
|
||||
|
||||
> To create a content script, see [Entrypoint Types](/guide/essentials/entrypoints#content-scripts).
|
||||
|
||||
## Context
|
||||
|
||||
The first argument to a content script's `main` function is it's "context".
|
||||
The first argument to a content script's `main` function is its "context".
|
||||
|
||||
```ts
|
||||
// entrypoints/content.ts
|
||||
// entrypoints/example.content.ts
|
||||
export default defineContentScript({
|
||||
main(ctx) {},
|
||||
});
|
||||
@@ -62,7 +64,7 @@ In regular web extensions, CSS for content scripts is usually a separate CSS fil
|
||||
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
|
||||
// entrypoints/example.content/index.ts
|
||||
import './style.css';
|
||||
|
||||
export default defineContentScript({
|
||||
@@ -78,16 +80,16 @@ To create a standalone content script that only includes a CSS file:
|
||||
// wxt.config.ts
|
||||
export default defineConfig({
|
||||
hooks: {
|
||||
"build:manifestGenerated": (wxt, manifest) => {
|
||||
'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: ["*://*/*"]
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
css: ['content-scripts/example.css'],
|
||||
matches: ['*://*/*'],
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## UI
|
||||
@@ -198,6 +200,7 @@ export default defineContentScript({
|
||||
```ts [Svelte]
|
||||
// entrypoints/example-ui.content/index.ts
|
||||
import App from './App.svelte';
|
||||
import { mount, unmount } from 'svelte';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
@@ -208,14 +211,13 @@ export default defineContentScript({
|
||||
anchor: 'body',
|
||||
onMount: (container) => {
|
||||
// Create the Svelte app inside the UI container
|
||||
const app = new App({
|
||||
mount(App, {
|
||||
target: container,
|
||||
});
|
||||
return app;
|
||||
},
|
||||
onRemove: (app) => {
|
||||
// Destroy the app when the UI is removed
|
||||
app.$destroy();
|
||||
unmount(app);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -379,6 +381,7 @@ export default defineContentScript({
|
||||
// 1. Import the style
|
||||
import './style.css';
|
||||
import App from './App.svelte';
|
||||
import { mount, unmount } from 'svelte';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
@@ -393,14 +396,13 @@ export default defineContentScript({
|
||||
anchor: 'body',
|
||||
onMount: (container) => {
|
||||
// Create the Svelte app inside the UI container
|
||||
const app = new App({
|
||||
mount(App, {
|
||||
target: container,
|
||||
});
|
||||
return app;
|
||||
},
|
||||
onRemove: (app) => {
|
||||
onRemove: () => {
|
||||
// Destroy the app when the UI is removed
|
||||
app?.$destroy();
|
||||
unmount(app);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -566,6 +568,20 @@ export default defineContentScript({
|
||||
});
|
||||
```
|
||||
|
||||
```json
|
||||
export default defineConfig({
|
||||
manifest: {
|
||||
// ...
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: ["example-main-world.js"],
|
||||
matches: ["*://*/*"],
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
`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.
|
||||
|
||||
@@ -28,7 +28,7 @@ For web extensions, there are two types of entrypoints:
|
||||
- **Listed**: Referenced in the `manifest.json`
|
||||
- **Unlisted**: Not referenced in the `manifest.json`
|
||||
|
||||
Throughout the rest of WXT's documentation, listed files are referred to by name. For example:
|
||||
Throughout the rest of WXT's documentation, listed entrypoints are referred to by name. For example:
|
||||
|
||||
- Popup
|
||||
- Options
|
||||
@@ -42,7 +42,7 @@ Some examples of "unlisted" entrypoints:
|
||||
- JS files injected by content scripts into the page's main world
|
||||
|
||||
:::tip
|
||||
Regardless of whether a entrypoint is listed or unlisted, it will still be bundled into your extension and be available at runtime.
|
||||
Regardless of whether an entrypoint is listed or unlisted, it will still be bundled into your extension and be available at runtime.
|
||||
:::
|
||||
|
||||
## Adding Entrypoints
|
||||
@@ -72,7 +72,7 @@ Refer to the [Entrypoint Types](#entrypoint-types) section for the full list of
|
||||
|
||||
## Defining Manifest Options
|
||||
|
||||
Most listed entrypoints have options that need to be added to the `manifest.json`. With WXT however, instead of defining the options in a separate file, _you define these options inside the entrypoint file itself_.
|
||||
Most listed entrypoints have options that need to be added to the `manifest.json`. However with WXT, instead of defining the options in a separate file, _you define these options inside the entrypoint file itself_.
|
||||
|
||||
For example, here's how to define `matches` for content scripts:
|
||||
|
||||
@@ -86,6 +86,17 @@ export default defineContentScript({
|
||||
});
|
||||
```
|
||||
|
||||
For HTML entrypoints, options are configured as `<meta>` tags. For example, to use a `page_action` for your MV2 popup:
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta name="manifest.type" content="page_action" />
|
||||
</head>
|
||||
</html>
|
||||
```
|
||||
|
||||
> Refer to the [Entrypoint Types](#entrypoint-types) sections for a list of options configurable inside each entrypoint, and how to define them.
|
||||
|
||||
When building your extension, WXT will look at the options defined in your entrypoints, and generate the manifest accordingly.
|
||||
@@ -542,4 +553,4 @@ const url = browser.runtime.getURL('/<name>.js');
|
||||
console.log(url); // "chrome-extension://<id>/<name>.js"
|
||||
```
|
||||
|
||||
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).
|
||||
You are responsible for loading/running these scripts where needed. If necessary, don't forget to add the script and/or any related assets to [`web_accessible_resources`](https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources).
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
# ES Modules
|
||||
|
||||
Currently, ESM entrypoints are opt-in, so you must configure each entrypoint with that in mind.
|
||||
You source code should always be written as ESM. However, you have some control whether an entrypoint is bundled as ESM.
|
||||
|
||||
## HTML Pages <Badge type="warning" text="≥0.0.1" />
|
||||
|
||||
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"`:
|
||||
Vite only supports bundling JS from HTML pages as ESM. Ensure you have added `type="module"` to your `<script>` tags:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```html
|
||||
@@ -16,7 +14,7 @@ To make a script ESM, add `type="module"`:
|
||||
|
||||
## Background <Badge type="warning" text="≥0.16.0" />
|
||||
|
||||
In your background script, set `type: "module"`:
|
||||
By default, your background will be bundled into a single file as IIFE. You can change this by setting `type: "module"` in your background entrypoint:
|
||||
|
||||
```ts
|
||||
export default defineBackground({
|
||||
@@ -27,12 +25,14 @@ export default defineBackground({
|
||||
});
|
||||
```
|
||||
|
||||
This will change the output format to ESM, enable code-spliting between your background script and HTML pages, and set `"type": "module"` in your manifest.
|
||||
|
||||
:::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.
|
||||
WXT does not yet include built-in support for bundling content scripts as ESM. 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.
|
||||
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 learn how.
|
||||
|
||||
@@ -81,6 +81,10 @@ However, it is recommended you stick with the vanilla API (or a package based on
|
||||
- Translations are not bundled multiple times, keeping your extension small
|
||||
- Zero configuration
|
||||
|
||||
However, there is one major downside to the vanilla API and any packages built on top of it:
|
||||
|
||||
- Language cannot be changed without changing your browser/system language
|
||||
|
||||
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)
|
||||
|
||||
@@ -14,3 +14,4 @@ Here are some popular messaging libraries that support all browsers and work wit
|
||||
- [`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.
|
||||
- [`Comctx`](https://github.com/molvqingtai/comctx) - Cross-context RPC solution with type safety and flexible adapters.
|
||||
|
||||
@@ -59,24 +59,24 @@ After enabling it, your project structure should look like this:
|
||||
<!-- prettier-ignore -->
|
||||
```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
|
||||
📁 .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
|
||||
|
||||
@@ -121,3 +121,4 @@ Once you've run the `dev` command, continue to [Next Steps](#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
|
||||
- Checkout the [community page](/guide/resources/community) for a list of resources made by the community!
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Community
|
||||
|
||||
This page is dedicated to all the awesome people how have made something for WXT or that works with WXT. Blog posts, YouTube videos, NPM packages, etc. If a section doesn't exist for the thing you made, add one!
|
||||
|
||||
[[toc]]
|
||||
|
||||
## Blog Posts
|
||||
|
||||
- [Building Modern Cross Browser Web Extensions](https://aabidk.dev/tags/wxt/) by Aabid ([@aabidk20](https://github.com/aabidk20))
|
||||
|
||||
## NPM Packages
|
||||
|
||||
- [`@webext-core/*`](https://webext-core.aklinker1.io/): Easy-to-use utilities for writing and testing web extensions that work on all browsers.
|
||||
- [`Comctx`](https://github.com/molvqingtai/comctx): Cross-context RPC solution with type safety and flexible adapters.
|
||||
@@ -10,6 +10,7 @@ Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework)
|
||||
|
||||
| Features | WXT | Plasmo | CRXJS |
|
||||
| ------------------------------------------------------- | :-----: | :-----: | :-----: |
|
||||
| Maintained | ✅ | 🟡 [^n] | 🟡 [^m] |
|
||||
| Supports all browsers | ✅ | ✅ | 🟡 [^j] |
|
||||
| MV2 Support | ✅ | ✅ | 🟡 [^a] |
|
||||
| MV3 Support | ✅ | ✅ | 🟡 [^a] |
|
||||
@@ -64,3 +65,7 @@ Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework)
|
||||
[^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.
|
||||
|
||||
[^m]: See [crxjs/chrome-extension-tools#974](https://github.com/crxjs/chrome-extension-tools/discussions/974)
|
||||
|
||||
[^n]: Appears to be in maintenance mode with little to no maintainers nor feature development happening and _(see [wxt-dev/wxt#1404 (comment)](https://github.com/wxt-dev/wxt/pull/1404#issuecomment-2643089518))_
|
||||
|
||||
+136
-36
@@ -28,47 +28,147 @@ See https://wxt.dev/guide/essentials/config/browser-startup.html#persist-data
|
||||
|
||||
## My component library doesn't work in content scripts!
|
||||
|
||||
Component libraries place their CSS in the document's `<head>` by default. When using `createShadowRootUi`, your UI is isolated from the document's styles because it's inside a ShadowRoot.
|
||||
This is usually caused by one of two things (or both) when using `createShadowRootUi`:
|
||||
|
||||
To fix this, you need to tell your component library to insert it's CSS inside the shadow root. Here's the docs for a couple of popular libraries:
|
||||
1. Styles are added outside the `ShadowRoot`
|
||||
|
||||
- React
|
||||
- Ant Design: [`StyleProvider`](https://ant.design/docs/react/compatible-style#shadow-dom-usage)
|
||||
- Mantine: [`MantineProvider#getRootElement` and `MantineProvider#cssVariablesSelector`](https://mantine.dev/theming/mantine-provider/)
|
||||
:::details
|
||||
Some component libraries manually add CSS to the page by adding a `<style>` or `<link>` element. They place this element in the document's `<head>` by default. This causes your styles to be placed outside the `ShadowRoot` and it's isolation blocks the styles from being applied to your UI.
|
||||
|
||||
> If your library isn't listed above, try searching it's docs/issues for "shadow root", "shadow dom", or "css container".
|
||||
When a library does this, **you need to tell the library where to put its styles**. Here's the documentation for a few popular component libraries:
|
||||
|
||||
`createShadowRootUi` provides it's own `<head>` element inside the shadow root, so that were you should tell the library to add the CSS. Here's an example with Ant Design:
|
||||
- Ant Design: [`StyleProvider`](https://ant.design/docs/react/compatible-style#shadow-dom-usage)
|
||||
- Mantine: [`MantineProvider#getRootElement` and `MantineProvider#cssVariablesSelector`](https://mantine.dev/theming/mantine-provider/)
|
||||
|
||||
```tsx
|
||||
import { StyleProvider } from '@ant-design/cssinjs'; // [!code ++]
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App.tsx';
|
||||
> If your library isn't listed above, try searching it's docs/issues for "shadow root", "shadow dom", or "css container". Not all libraries support shadow DOMs, you may have to open an issue to request this feature.
|
||||
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
name: 'example-ui',
|
||||
position: 'inline',
|
||||
anchor: 'body',
|
||||
onMount: (container) => { // [!code --]
|
||||
onMount: (container, shadow) => { // [!code ++]
|
||||
const cssContainer = shadow.querySelector("head")!; // [!code ++]
|
||||
const root = ReactDOM.createRoot(container);
|
||||
root.render(
|
||||
<StyleProvider container={cssContainer}> // [!code ++]
|
||||
<App />
|
||||
</StyleProvider> // [!code ++]
|
||||
);
|
||||
return root;
|
||||
},
|
||||
onRemove: (root) => {
|
||||
root?.unmount();
|
||||
},
|
||||
});
|
||||
```
|
||||
Here's an example of configuring Antd's styles:
|
||||
|
||||
Note that this doesn't effect all component libraries, just ones that inject CSS themselves rather than having you import their CSS. This approach is more prevailent in the React community, but not limited to it. That's why only React libraries are listed above. Vuetify, for example, works just fine because you import its CSS - WXT picks up on this and the CSS is added inside the shadow root automatically:
|
||||
```tsx
|
||||
import { StyleProvider } from '@ant-design/cssinjs';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App.tsx';
|
||||
|
||||
```ts
|
||||
import 'vuetify/styles'; // <-- This line imports the CSS, just like importing a .css file
|
||||
import { createVuetify } from 'vuetify';
|
||||
```
|
||||
const ui = await create`ShadowRoot`Ui(ctx, {
|
||||
// ...
|
||||
onMount: (container, shadow) => {
|
||||
const cssContainer = shadow.querySelector('head')!;
|
||||
const root = ReactDOM.createRoot(container);
|
||||
root.render(
|
||||
<StyleProvider container={cssContainer}>
|
||||
<App />
|
||||
</StyleProvider>,
|
||||
);
|
||||
return root;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
2. UI elements are added outside the `ShadowRoot`
|
||||
|
||||
::::::details
|
||||
This is mostly caused by `Teleport` or `Portal` components that render an element somewhere else in the DOM, usually in the document's `<body>`. This is usually done for dialogs or popover components. This renders the element is outside the `ShadowRoot`, so styles are not applied to it.
|
||||
|
||||
To fix this, **you need to both provide a target to your app AND pass the target to the `Teleport`/`Portal`**.
|
||||
|
||||
First, store the reference to the `ShadowRoot`'s `<body>` element (not the document's `<body>`):
|
||||
|
||||
:::code-group
|
||||
|
||||
```ts [Vue]
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
const ui = await create`ShadowRoot`Ui(ctx, {
|
||||
// ...
|
||||
onMount: (container, shadow) => {
|
||||
const teleportTarget = shadow.querySelector('body')!;
|
||||
const app = createApp(App)
|
||||
.provide('TeleportTarget', teleportTarget)
|
||||
.mount(container);
|
||||
return app;
|
||||
},
|
||||
});
|
||||
ui.mount();
|
||||
```
|
||||
|
||||
```tsx [React]
|
||||
// hooks/PortalTargetContext.ts
|
||||
import { createContext } from 'react';
|
||||
|
||||
export const PortalTargetContext = createContext<HTMLElement>();
|
||||
|
||||
// entrypoints/example.content.ts
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App.tsx';
|
||||
import PortalTargetContext from '~/hooks/PortalTargetContext';
|
||||
|
||||
const ui = await create`ShadowRoot`Ui(ctx, {
|
||||
// ...
|
||||
onMount: (container, shadow) => {
|
||||
const portalTarget = shadow.querySelector('body')!;
|
||||
const root = ReactDOM.createRoot(container);
|
||||
root.render(
|
||||
<PortalTargetContext.Provider value={portalTarget}>
|
||||
<App />
|
||||
</PortalTargetContext.Provider>,
|
||||
);
|
||||
return root;
|
||||
},
|
||||
});
|
||||
ui.mount();
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then use the reference when teleporting/portaling part of your UI to a different place in the DOM:
|
||||
|
||||
:::code-group
|
||||
|
||||
```vue [Vue]
|
||||
<script lang="ts" setup>
|
||||
import { Teleport } from 'vue';
|
||||
|
||||
const teleportTarget = inject('TeleportTarget');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Teleport :to="teleportTarget">
|
||||
<dialog>My dialog</dialog>
|
||||
</Teleport>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
```tsx [React]
|
||||
import { useContext } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import PortalTargetContext from '~/hooks/PortalTargetContext';
|
||||
|
||||
const MyComponent = () => {
|
||||
const portalTarget = useContext(PortalTargetContext);
|
||||
|
||||
return <div>{createPortal(<dialog>My dialog</dialog>, portalTarget)}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
If you use ShadCN, [see this blog post](https://aabidk.dev/blog/building-modern-cross-browser-web-extensions-content-scripts-and-ui/#using-radixui-portals-to-move-the-dialog-to-shadow-dom).
|
||||
|
||||
::::::
|
||||
|
||||
Both issues have the same cause: the library puts something outside the `ShadowRoot`, and the `ShadowRoot`'s isolation prevents CSS from being applied to your UI.
|
||||
|
||||
Both issues have the same fix: tell the library to put elements inside the `ShadowRoot`, not outside it. See the details above for more information and example fixes for each problem.
|
||||
|
||||
## Is there an LLM trained on WXT's docs that I chat with?
|
||||
|
||||
Not yet, but we're working on it. For now, https://wxt.dev hosts pre-aggregated and pre-formatted knowledge files containing all the docs from this website:
|
||||
|
||||
- Index listing available knowledge files: https://wxt.dev/knowledge/index.json
|
||||
|
||||
You don't need to crawl the entire website, these files already contain all the relevant docs for training a LLM on WXT. But feel free to crawl it and generate your own files if you want!
|
||||
|
||||
+26
-23
@@ -4,7 +4,7 @@
|
||||
"engines": {
|
||||
"node": ">=18.20.3"
|
||||
},
|
||||
"packageManager": "pnpm@9.13.0",
|
||||
"packageManager": "pnpm@10.5.2",
|
||||
"scripts": {
|
||||
"check": "check && pnpm -r --sequential run check",
|
||||
"test": "pnpm -r --sequential run test run",
|
||||
@@ -17,28 +17,31 @@
|
||||
"docs:preview": "pnpm -s docs:gen && vitepress preview docs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/buildc": "^1.1.4",
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@vitest/coverage-v8": "^2.1.4",
|
||||
"changelogen": "^0.5.7",
|
||||
"consola": "^3.2.3",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fs-extra": "^11.2.0",
|
||||
"lint-staged": "^15.2.10",
|
||||
"markdown-it-footnote": "^4.0.0",
|
||||
"nano-spawn": "^0.2.0",
|
||||
"prettier": "^3.3.3",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"tsx": "4.15.7",
|
||||
"typedoc": "^0.25.4",
|
||||
"typedoc-plugin-frontmatter": "^1.1.0",
|
||||
"typedoc-plugin-markdown": "4.0.0-next.23",
|
||||
"typedoc-vitepress-theme": "1.0.0-next.3",
|
||||
"typescript": "^5.6.3",
|
||||
"vitepress": "^1.5.0",
|
||||
"vitest-mock-extended": "^2.0.2",
|
||||
"vue": "^3.5.12",
|
||||
"@aklinker1/buildc": "catalog:",
|
||||
"@aklinker1/check": "catalog:",
|
||||
"@commitlint/config-conventional": "catalog:",
|
||||
"@commitlint/types": "catalog:",
|
||||
"@types/fs-extra": "catalog:",
|
||||
"@vitest/coverage-v8": "catalog:",
|
||||
"changelogen": "catalog:",
|
||||
"consola": "catalog:",
|
||||
"fast-glob": "catalog:",
|
||||
"fs-extra": "catalog:",
|
||||
"lint-staged": "catalog:",
|
||||
"markdown-it-footnote": "catalog:",
|
||||
"nano-spawn": "catalog:",
|
||||
"prettier": "catalog:",
|
||||
"simple-git-hooks": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"typedoc": "catalog:",
|
||||
"typedoc-plugin-frontmatter": "catalog:",
|
||||
"typedoc-plugin-markdown": "catalog:",
|
||||
"typedoc-vitepress-theme": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"vitepress": "catalog:",
|
||||
"vitepress-knowledge": "catalog:",
|
||||
"vitest-mock-extended": "catalog:",
|
||||
"vue": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
|
||||
@@ -44,17 +44,17 @@
|
||||
"peerDependencies": {
|
||||
"wxt": ">=0.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"oxlint": "^0.11.1",
|
||||
"publint": "^0.2.12",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"wxt": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"defu": "^6.1.4",
|
||||
"fs-extra": "^11.2.0",
|
||||
"sharp": "^0.33.5"
|
||||
"defu": "catalog:",
|
||||
"fs-extra": "catalog:",
|
||||
"sharp": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "catalog:",
|
||||
"oxlint": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,6 +354,7 @@ You'll need to configure it the extension so it knows where your localization fi
|
||||
# You can check available language ids here: https://code.visualstudio.com/docs/languages/identifiers
|
||||
languageIds:
|
||||
- typescript
|
||||
- typescriptreact
|
||||
|
||||
# Look for t("...")
|
||||
usageMatchRegex:
|
||||
|
||||
+13
-12
@@ -19,15 +19,16 @@
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"scripts": {
|
||||
"build": "buildc -- unbuild",
|
||||
"check": "buildc --deps-only -- check",
|
||||
"test": "buildc --deps-only -- vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"chokidar": "^3.6.0",
|
||||
"confbox": "^0.1.8",
|
||||
"fast-glob": "^3.3.2"
|
||||
"chokidar": "catalog:",
|
||||
"confbox": "catalog:",
|
||||
"fast-glob": "catalog:"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"wxt": ">=0.19.7"
|
||||
@@ -38,15 +39,15 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"@types/chrome": "^0.0.280",
|
||||
"@types/node": "^20.17.6",
|
||||
"oxlint": "^0.11.1",
|
||||
"publint": "^0.2.12",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"vitest": "^2.1.4",
|
||||
"vitest-plugin-random-seed": "^1.1.0",
|
||||
"@aklinker1/check": "catalog:",
|
||||
"@types/chrome": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"oxlint": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"vitest": "catalog:",
|
||||
"vitest-plugin-random-seed": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
},
|
||||
"main": "./dist/index.cjs",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { defineBuildConfig } from 'unbuild';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
export default defineBuildConfig({
|
||||
rootDir: 'modules',
|
||||
rootDir: resolve(__dirname, 'modules'),
|
||||
outDir: resolve(__dirname, 'dist'),
|
||||
entries: [{ input: 'react.ts', name: 'index' }],
|
||||
rollup: {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"version": "1.1.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
@@ -47,17 +48,17 @@
|
||||
"wxt": ">=0.19.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vitejs/plugin-react": "^4.3.4"
|
||||
"@vitejs/plugin-react": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"publint": "^0.2.12",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"@aklinker1/check": "catalog:",
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-dom": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"react": "catalog:",
|
||||
"react-dom": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { defineBuildConfig } from 'unbuild';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
export default defineBuildConfig({
|
||||
rootDir: 'modules',
|
||||
rootDir: resolve(__dirname, 'modules'),
|
||||
outDir: resolve(__dirname, 'dist'),
|
||||
entries: [{ input: 'solid.ts', name: 'index' }],
|
||||
rollup: {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"version": "1.1.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
@@ -47,14 +48,14 @@
|
||||
"wxt": ">=0.19.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"vite-plugin-solid": "^2.10.2"
|
||||
"vite-plugin-solid": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"publint": "^0.2.12",
|
||||
"solid-js": "^1.9.3",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"@aklinker1/check": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"solid-js": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## v2.0.3
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/module-svelte-v2.0.2...module-svelte-v2.0.3)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Upgrade `vite-plugin-svelte` to support Vite 6 ([#1375](https://github.com/wxt-dev/wxt/pull/1375))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Eli ([@lishaduck](http://github.com/lishaduck))
|
||||
|
||||
## v2.0.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/module-svelte-v2.0.1...module-svelte-v2.0.2)
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"version": "2.0.2",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"version": "2.0.3",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
@@ -46,13 +47,13 @@
|
||||
"svelte": ">=5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.0"
|
||||
"@sveltejs/vite-plugin-svelte": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"publint": "^0.2.12",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"@aklinker1/check": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"version": "1.0.2",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
@@ -45,13 +46,13 @@
|
||||
"wxt": ">=0.19.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.0"
|
||||
"@vitejs/plugin-vue": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"publint": "^0.2.12",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"@aklinker1/check": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
## v1.1.0
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/storage-v1.0.1...storage-v1.1.0)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Add `storage.clear` ([#1368](https://github.com/wxt-dev/wxt/pull/1368))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Update link ([654a54a](https://github.com/wxt-dev/wxt/commit/654a54a))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Chengxi ([@chengxilo](http://github.com/chengxilo))
|
||||
- Aaron ([@aklinker1](http://github.com/aklinker1))
|
||||
|
||||
## v1.0.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/storage-v1.0.0...storage-v1.0.1)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@wxt-dev/storage",
|
||||
"description": "Web extension storage API provided by WXT, supports all browsers.",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -23,24 +23,25 @@
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"scripts": {
|
||||
"build": "buildc -- unbuild",
|
||||
"check": "buildc --deps-only -- check",
|
||||
"test": "buildc --deps-only -- vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-mutex": "^0.5.0",
|
||||
"dequal": "^2.0.3"
|
||||
"async-mutex": "catalog:",
|
||||
"dequal": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"@types/chrome": "^0.0.268",
|
||||
"@webext-core/fake-browser": "^1.3.1",
|
||||
"oxlint": "^0.9.9",
|
||||
"publint": "^0.2.11",
|
||||
"typescript": "^5.6.2",
|
||||
"unbuild": "^2.0.0",
|
||||
"vitest": "^2.0.0"
|
||||
"@aklinker1/check": "catalog:",
|
||||
"@types/chrome": "catalog:",
|
||||
"@webext-core/fake-browser": "catalog:",
|
||||
"oxlint": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
},
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@@ -489,6 +489,18 @@ describe('Storage Utils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('clear', () => {
|
||||
it('should remove all items', async () => {
|
||||
await fakeBrowser.storage[storageArea].set({
|
||||
one: 1,
|
||||
two: 2,
|
||||
});
|
||||
|
||||
await storage.clear(storageArea);
|
||||
expect(await fakeBrowser.storage[storageArea].get()).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeMeta', () => {
|
||||
it('should remove all metadata', async () => {
|
||||
await fakeBrowser.storage[storageArea].set({ count$: { v: 4 } });
|
||||
|
||||
@@ -326,6 +326,10 @@ function createStorage(): WxtStorage {
|
||||
}),
|
||||
);
|
||||
},
|
||||
clear: async (base) => {
|
||||
const driver = getDriver(base);
|
||||
await driver.clear();
|
||||
},
|
||||
removeMeta: async (key, properties) => {
|
||||
const { driver, driverKey } = resolveKey(key);
|
||||
await removeMeta(driver, driverKey, properties);
|
||||
@@ -390,7 +394,7 @@ function createStorage(): WxtStorage {
|
||||
(await migrations?.[migrateToVersion]?.(migratedValue)) ??
|
||||
migratedValue;
|
||||
} catch (err) {
|
||||
throw Error(`v${migrateToVersion} migration failed for "${key}"`, {
|
||||
throw new MigrationError(key, migrateToVersion, {
|
||||
cause: err,
|
||||
});
|
||||
}
|
||||
@@ -534,6 +538,9 @@ function createDriver(storageArea: StorageArea): WxtStorageDriver {
|
||||
removeItems: async (keys) => {
|
||||
await getStorageArea().remove(keys);
|
||||
},
|
||||
clear: async () => {
|
||||
await getStorageArea().clear();
|
||||
},
|
||||
snapshot: async () => {
|
||||
return await getStorageArea().get();
|
||||
},
|
||||
@@ -674,6 +681,12 @@ export interface WxtStorage {
|
||||
| { item: WxtStorageItem<any, any>; options?: RemoveItemOptions }
|
||||
>,
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* Removes all items from the provided storage area.
|
||||
*/
|
||||
clear(base: StorageArea): Promise<void>;
|
||||
|
||||
/**
|
||||
* Remove the entire metadata for a key, or specific properties by name.
|
||||
*
|
||||
@@ -712,7 +725,7 @@ export interface WxtStorage {
|
||||
/**
|
||||
* Define a storage item with a default value, type, or versioning.
|
||||
*
|
||||
* Read full docs: https://wxt.dev/guide/extension-apis/storage.html#defining-storage-items
|
||||
* Read full docs: https://wxt.dev/storage.html#defining-storage-items
|
||||
*/
|
||||
defineItem<TValue, TMetadata extends Record<string, unknown> = {}>(
|
||||
key: StorageItemKey,
|
||||
@@ -730,6 +743,7 @@ interface WxtStorageDriver {
|
||||
setItems(values: Array<{ key: string; value: any }>): Promise<void>;
|
||||
removeItem(key: string): Promise<void>;
|
||||
removeItems(keys: string[]): Promise<void>;
|
||||
clear(): Promise<void>;
|
||||
snapshot(): Promise<Record<string, unknown>>;
|
||||
restoreSnapshot(data: Record<string, unknown>): Promise<void>;
|
||||
watch<T>(key: string, cb: WatchCallback<T | null>): Unwatch;
|
||||
|
||||
@@ -38,10 +38,10 @@ The module can be configured via the `unocss` config:
|
||||
export default defineConfig({
|
||||
modules: ['@wxt-dev/unocss'],
|
||||
unocss: {
|
||||
// Will only apply unocss for popup/main.ts
|
||||
entrypoints: ['popup/main.ts'],
|
||||
// Exclude unocss from running for the background
|
||||
excludeEntrypoints: ['background'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
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).
|
||||
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/unocss/src/index.ts).
|
||||
|
||||
@@ -40,16 +40,16 @@
|
||||
"wxt": ">=0.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"oxlint": "^0.11.1",
|
||||
"publint": "^0.2.12",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"unocss": "^0.64.0",
|
||||
"@aklinker1/check": "catalog:",
|
||||
"oxlint": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"unocss": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"defu": "^6.1.4",
|
||||
"fast-glob": "^3.3.2"
|
||||
"defu": "catalog:",
|
||||
"fast-glob": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,20 +18,20 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@wxt-dev/i18n": "workspace:*",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
"react": "catalog:",
|
||||
"react-dom": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chrome": "^0.0.280",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"@types/chrome": "catalog:",
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-dom": "catalog:",
|
||||
"@wxt-dev/auto-icons": "workspace:*",
|
||||
"@wxt-dev/unocss": "workspace:*",
|
||||
"sass": "^1.80.7",
|
||||
"typescript": "^5.6.3",
|
||||
"unocss": "^0.64.0",
|
||||
"vitest": "^2.1.4",
|
||||
"vitest-plugin-random-seed": "^1.1.0",
|
||||
"sass": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unocss": "catalog:",
|
||||
"vitest": "catalog:",
|
||||
"vitest-plugin-random-seed": "catalog:",
|
||||
"wxt": "workspace:*"
|
||||
},
|
||||
"buildc": {
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import 'uno.css';
|
||||
import './style.css';
|
||||
import manualStyle from './manual-style.css?inline';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['https://*.duckduckgo.com/*'],
|
||||
cssInjectionMode: 'ui',
|
||||
|
||||
async main(ctx) {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = manualStyle;
|
||||
document.head.append(style);
|
||||
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
name: 'demo-ui',
|
||||
position: 'inline',
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
body {
|
||||
padding: 2rem;
|
||||
background-color: blanchedalmond;
|
||||
}
|
||||
@@ -1,5 +1,100 @@
|
||||
# Changelog
|
||||
|
||||
## v0.19.28
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.27...wxt-v0.19.28)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Ignore `manifest.manifest_version` option and warn about incorrect usage ([#1419](https://github.com/wxt-dev/wxt/pull/1419))
|
||||
- Resolve wxt modules from the root ([#1417](https://github.com/wxt-dev/wxt/pull/1417))
|
||||
- Properly detect and reload changed files when using Vite's `?suffix` imports ([#1432](https://github.com/wxt-dev/wxt/pull/1432))
|
||||
- Regression on variable expansion in dotenv files ([#1449](https://github.com/wxt-dev/wxt/pull/1449))
|
||||
- Allow vite 6.0.9+ ([#1497](https://github.com/wxt-dev/wxt/pull/1497))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Host pre-aggregated LLM knowledge files ([#1355](https://github.com/wxt-dev/wxt/pull/1355))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Add funding links to `package.json` files ([#1446](https://github.com/wxt-dev/wxt/pull/1446))
|
||||
- Use PNPM 10's new catelog feature ([#1493](https://github.com/wxt-dev/wxt/pull/1493))
|
||||
- Move production dependencies to PNPM 10 catelog ([#1494](https://github.com/wxt-dev/wxt/pull/1494))
|
||||
- **deps:** Upgrade to Vite 6 and related dependencies ([#1496](https://github.com/wxt-dev/wxt/pull/1496))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron ([@aklinker1](http://github.com/aklinker1))
|
||||
- Stefan Maric <me@stefanmaric.com>
|
||||
- Okinea Dev ([@okineadev](http://github.com/okineadev))
|
||||
- 1natsu ([@1natsu172](http://github.com/1natsu172))
|
||||
- Alec Larson ([@aleclarson](http://github.com/aleclarson))
|
||||
|
||||
## v0.19.27
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.26...wxt-v0.19.27)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Allow `vite-node@^3.0.0` ([#1378](https://github.com/wxt-dev/wxt/pull/1378))
|
||||
- Use path triple slash directive for types that are referenced via path ([#1407](https://github.com/wxt-dev/wxt/pull/1407))
|
||||
- Support `publish-browser-extension` v3.0.0 ([ac92d40](https://github.com/wxt-dev/wxt/commit/ac92d40))
|
||||
- Respect `inlineConfig.mode` when setting NODE_ENV ([#1416](https://github.com/wxt-dev/wxt/pull/1416))
|
||||
- Auto-import does not work when using `@vitejs/plugin-vue` alone ([#1412](https://github.com/wxt-dev/wxt/pull/1412))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Jaguar Zhou ([@aiktb](http://github.com/aiktb))
|
||||
- Alec Larson ([@aleclarson](http://github.com/aleclarson))
|
||||
- Aaron ([@aklinker1](http://github.com/aklinker1))
|
||||
- St3h3n <st3h3n@gmail.com>
|
||||
- Eli ([@lishaduck](http://github.com/lishaduck))
|
||||
|
||||
## v0.19.26
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.25...wxt-v0.19.26)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- **context:** Deduplicate `wxt:content-script-started` ([#1364](https://github.com/wxt-dev/wxt/pull/1364))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Deniz Uğur ([@DenizUgur](http://github.com/DenizUgur))
|
||||
|
||||
## v0.19.25
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.24...wxt-v0.19.25)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Drop support for vite 6.0.9+ until websocket fix is finished ([8e2badc](https://github.com/wxt-dev/wxt/commit/8e2badc))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron ([@aklinker1](http://github.com/aklinker1))
|
||||
|
||||
## v0.19.24
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.23...wxt-v0.19.24)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- **init:** Remove "experimental" from bun package manager ([b150a52](https://github.com/wxt-dev/wxt/commit/b150a52))
|
||||
- **web-ext:** Correctly pass `browserConsole` option to open devtools in Firefox ([#1308](https://github.com/wxt-dev/wxt/pull/1308))
|
||||
- `autoMount` not working if anchor is already present ([#1350](https://github.com/wxt-dev/wxt/pull/1350))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Fix typo in CLI docs ([028c601](https://github.com/wxt-dev/wxt/commit/028c601))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- 1natsu ([@1natsu172](http://github.com/1natsu172))
|
||||
- Paulo Pinto ([@psrpinto](https://github.com/psrpinto))
|
||||
- Aaron ([@aklinker1](http://github.com/aklinker1))
|
||||
|
||||
## v0.19.23
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.22...wxt-v0.19.23)
|
||||
@@ -2775,4 +2870,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))
|
||||
- Create release workflow ([#13](https://github.com/wxt-dev/wxt/pull/13))
|
||||
@@ -52,10 +52,10 @@ describe('Auto Imports', () => {
|
||||
----------------------------------------
|
||||
// Generated by wxt
|
||||
/// <reference types="wxt/vite-builder-env" />
|
||||
/// <reference types="./types/paths.d.ts" />
|
||||
/// <reference types="./types/i18n.d.ts" />
|
||||
/// <reference types="./types/globals.d.ts" />
|
||||
/// <reference types="./types/imports.d.ts" />
|
||||
/// <reference path="./types/paths.d.ts" />
|
||||
/// <reference path="./types/i18n.d.ts" />
|
||||
/// <reference path="./types/globals.d.ts" />
|
||||
/// <reference path="./types/imports.d.ts" />
|
||||
"
|
||||
`);
|
||||
});
|
||||
@@ -91,9 +91,9 @@ describe('Auto Imports', () => {
|
||||
----------------------------------------
|
||||
// Generated by wxt
|
||||
/// <reference types="wxt/vite-builder-env" />
|
||||
/// <reference types="./types/paths.d.ts" />
|
||||
/// <reference types="./types/i18n.d.ts" />
|
||||
/// <reference types="./types/globals.d.ts" />
|
||||
/// <reference path="./types/paths.d.ts" />
|
||||
/// <reference path="./types/i18n.d.ts" />
|
||||
/// <reference path="./types/globals.d.ts" />
|
||||
"
|
||||
`,
|
||||
);
|
||||
|
||||
@@ -236,10 +236,10 @@ describe('TypeScript Project', () => {
|
||||
----------------------------------------
|
||||
// Generated by wxt
|
||||
/// <reference types="wxt/vite-builder-env" />
|
||||
/// <reference types="./types/paths.d.ts" />
|
||||
/// <reference types="./types/i18n.d.ts" />
|
||||
/// <reference types="./types/globals.d.ts" />
|
||||
/// <reference types="./types/imports.d.ts" />
|
||||
/// <reference path="./types/paths.d.ts" />
|
||||
/// <reference path="./types/i18n.d.ts" />
|
||||
/// <reference path="./types/globals.d.ts" />
|
||||
/// <reference path="./types/imports.d.ts" />
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
+66
-64
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "wxt",
|
||||
"type": "module",
|
||||
"version": "0.19.23",
|
||||
"description": "Next gen framework for developing web extensions",
|
||||
"version": "0.19.28",
|
||||
"description": "⚡ Next-gen Web Extension Framework",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wxt-dev/wxt.git"
|
||||
@@ -22,6 +22,7 @@
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"files": [
|
||||
"bin",
|
||||
"dist"
|
||||
@@ -81,71 +82,72 @@
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@1natsu/wait-element": "^4.1.2",
|
||||
"@aklinker1/rollup-plugin-visualizer": "5.12.0",
|
||||
"@types/chrome": "^0.0.280",
|
||||
"@types/webextension-polyfill": "^0.12.1",
|
||||
"@webext-core/fake-browser": "^1.3.1",
|
||||
"@webext-core/isolated-element": "^1.1.2",
|
||||
"@webext-core/match-patterns": "^1.0.3",
|
||||
"@1natsu/wait-element": "catalog:",
|
||||
"@aklinker1/rollup-plugin-visualizer": "catalog:",
|
||||
"@types/chrome": "catalog:",
|
||||
"@types/webextension-polyfill": "catalog:",
|
||||
"@webext-core/fake-browser": "catalog:",
|
||||
"@webext-core/isolated-element": "catalog:",
|
||||
"@webext-core/match-patterns": "catalog:",
|
||||
"@wxt-dev/storage": "workspace:^1.0.0",
|
||||
"async-mutex": "^0.5.0",
|
||||
"c12": "^1.11.2",
|
||||
"cac": "^6.7.14",
|
||||
"chokidar": "^3.6.0",
|
||||
"ci-info": "^4.1.0",
|
||||
"consola": "^3.2.3",
|
||||
"defu": "^6.1.4",
|
||||
"dotenv": "^16.4.5",
|
||||
"esbuild": "^0.21.5",
|
||||
"fast-glob": "^3.3.2",
|
||||
"filesize": "^10.1.6",
|
||||
"fs-extra": "^11.2.0",
|
||||
"get-port-please": "^3.1.2",
|
||||
"giget": "^1.2.3",
|
||||
"hookable": "^5.5.3",
|
||||
"is-wsl": "^3.1.0",
|
||||
"jiti": "^1.21.6",
|
||||
"json5": "^2.2.3",
|
||||
"jszip": "^3.10.1",
|
||||
"linkedom": "^0.18.5",
|
||||
"magicast": "^0.3.5",
|
||||
"minimatch": "^10.0.1",
|
||||
"nano-spawn": "^0.2.0",
|
||||
"normalize-path": "^3.0.0",
|
||||
"nypm": "^0.3.12",
|
||||
"ohash": "^1.1.4",
|
||||
"open": "^10.1.0",
|
||||
"ora": "^8.1.1",
|
||||
"perfect-debounce": "^1.0.0",
|
||||
"picocolors": "^1.1.1",
|
||||
"prompts": "^2.4.2",
|
||||
"publish-browser-extension": "^2.2.2",
|
||||
"scule": "^1.3.0",
|
||||
"unimport": "^3.13.1",
|
||||
"vite": "^5.0.0 || ^6.0.0",
|
||||
"vite-node": "^2.1.4",
|
||||
"web-ext-run": "^0.2.1",
|
||||
"webextension-polyfill": "^0.12.0"
|
||||
"async-mutex": "catalog:",
|
||||
"c12": "catalog:",
|
||||
"cac": "catalog:",
|
||||
"chokidar": "catalog:",
|
||||
"ci-info": "catalog:",
|
||||
"consola": "catalog:",
|
||||
"defu": "catalog:",
|
||||
"dotenv": "catalog:",
|
||||
"dotenv-expand": "catalog:",
|
||||
"esbuild": "catalog:",
|
||||
"fast-glob": "catalog:",
|
||||
"filesize": "catalog:",
|
||||
"fs-extra": "catalog:",
|
||||
"get-port-please": "catalog:",
|
||||
"giget": "catalog:",
|
||||
"hookable": "catalog:",
|
||||
"import-meta-resolve": "catalog:",
|
||||
"is-wsl": "catalog:",
|
||||
"jiti": "catalog:",
|
||||
"json5": "catalog:",
|
||||
"jszip": "catalog:",
|
||||
"linkedom": "catalog:",
|
||||
"magicast": "catalog:",
|
||||
"minimatch": "catalog:",
|
||||
"nano-spawn": "catalog:",
|
||||
"normalize-path": "catalog:",
|
||||
"nypm": "catalog:",
|
||||
"ohash": "catalog:",
|
||||
"open": "catalog:",
|
||||
"ora": "catalog:",
|
||||
"perfect-debounce": "catalog:",
|
||||
"picocolors": "catalog:",
|
||||
"prompts": "catalog:",
|
||||
"publish-browser-extension": "catalog:",
|
||||
"scule": "catalog:",
|
||||
"unimport": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"vite-node": "catalog:",
|
||||
"web-ext-run": "catalog:",
|
||||
"webextension-polyfill": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.4.5",
|
||||
"@faker-js/faker": "^9.2.0",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/lodash.merge": "^4.6.9",
|
||||
"@types/node": "^20.17.6",
|
||||
"@types/normalize-path": "^3.0.2",
|
||||
"@types/prompts": "^2.4.9",
|
||||
"extract-zip": "^2.0.1",
|
||||
"happy-dom": "^15.11.4",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"oxlint": "^0.11.1",
|
||||
"publint": "^0.2.12",
|
||||
"tsx": "4.15.7",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"vitest": "^2.1.4",
|
||||
"vitest-plugin-random-seed": "^1.1.0"
|
||||
"@aklinker1/check": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@types/fs-extra": "catalog:",
|
||||
"@types/lodash.merge": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@types/normalize-path": "catalog:",
|
||||
"@types/prompts": "catalog:",
|
||||
"extract-zip": "catalog:",
|
||||
"happy-dom": "catalog:",
|
||||
"lodash.merge": "catalog:",
|
||||
"oxlint": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"unbuild": "catalog:",
|
||||
"vitest": "catalog:",
|
||||
"vitest-plugin-random-seed": "catalog:"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/chrome": {
|
||||
|
||||
@@ -6,8 +6,7 @@ import type {
|
||||
WxtResolvedUnimportOptions,
|
||||
} from '../types';
|
||||
import { type Unimport, createUnimport } from 'unimport';
|
||||
import { Plugin } from 'vite';
|
||||
import { extname } from 'node:path';
|
||||
import UnimportPlugin from 'unimport/unplugin';
|
||||
|
||||
export default defineWxtModule({
|
||||
name: 'wxt:built-in:unimport',
|
||||
@@ -53,38 +52,11 @@ export default defineWxtModule({
|
||||
|
||||
// Add vite plugin
|
||||
addViteConfig(wxt, () => ({
|
||||
plugins: [vitePlugin(unimport)],
|
||||
plugins: [UnimportPlugin.vite(options)],
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
export function vitePlugin(unimport: Unimport): Plugin {
|
||||
const ENABLED_EXTENSIONS = new Set([
|
||||
'.js',
|
||||
'.jsx',
|
||||
'.ts',
|
||||
'.tsx',
|
||||
'.vue',
|
||||
'.svelte',
|
||||
]);
|
||||
return {
|
||||
name: 'wxt:unimport',
|
||||
async transform(code, id) {
|
||||
// Don't transform dependencies
|
||||
if (id.includes('node_modules')) return;
|
||||
|
||||
// Don't transform non-js files
|
||||
if (!ENABLED_EXTENSIONS.has(extname(id))) return;
|
||||
|
||||
const injected = await unimport.injectImports(code, id);
|
||||
return {
|
||||
code: injected.code,
|
||||
map: injected.s.generateMap({ hires: 'boundary', source: id }),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function getImportsDeclarationEntry(
|
||||
unimport: Unimport,
|
||||
): Promise<WxtDirFileEntry> {
|
||||
|
||||
@@ -42,6 +42,7 @@ export class ContentScriptContext implements AbortController {
|
||||
private isTopFrame = window.self === window.top;
|
||||
private abortController: AbortController;
|
||||
private locationWatcher = createLocationWatcher(this);
|
||||
private receivedMessageIds = new Set<string>();
|
||||
|
||||
constructor(
|
||||
private readonly contentScriptName: string,
|
||||
@@ -233,19 +234,28 @@ export class ContentScriptContext implements AbortController {
|
||||
{
|
||||
type: ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE,
|
||||
contentScriptName: this.contentScriptName,
|
||||
messageId: Math.random().toString(36).slice(2),
|
||||
},
|
||||
'*',
|
||||
);
|
||||
}
|
||||
|
||||
verifyScriptStartedEvent(event: MessageEvent) {
|
||||
const isScriptStartedEvent =
|
||||
event.data?.type === ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE;
|
||||
const isSameContentScript =
|
||||
event.data?.contentScriptName === this.contentScriptName;
|
||||
const isNotDuplicate = !this.receivedMessageIds.has(event.data?.messageId);
|
||||
return isScriptStartedEvent && isSameContentScript && isNotDuplicate;
|
||||
}
|
||||
|
||||
listenForNewerScripts(options?: { ignoreFirstEvent?: boolean }) {
|
||||
let isFirst = true;
|
||||
|
||||
const cb = (event: MessageEvent) => {
|
||||
if (
|
||||
event.data?.type === ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE &&
|
||||
event.data?.contentScriptName === this.contentScriptName
|
||||
) {
|
||||
if (this.verifyScriptStartedEvent(event)) {
|
||||
this.receivedMessageIds.add(event.data.messageId);
|
||||
|
||||
const wasFirst = isFirst;
|
||||
isFirst = false;
|
||||
if (wasFirst && options?.ignoreFirstEvent) return;
|
||||
|
||||
@@ -546,6 +546,25 @@ describe('Content Script UIs', () => {
|
||||
] as const)(
|
||||
'built-in UI type: $name',
|
||||
({ name, createUiFunction, uiSelector }) => {
|
||||
it('should mount if an anchor already exists at the initialization', async () => {
|
||||
const onMount = vi.fn(appendTestApp);
|
||||
ui = await createUiFunction(ctx, {
|
||||
position: 'inline',
|
||||
onMount,
|
||||
anchor: `#parent > #${DYNAMIC_CHILD_ID}`,
|
||||
page: name === 'iframe' ? '/page.html' : undefined,
|
||||
name: 'test-component',
|
||||
});
|
||||
|
||||
appendTestElement({ id: DYNAMIC_CHILD_ID });
|
||||
ui.autoMount();
|
||||
await runMicrotasks();
|
||||
|
||||
await expect
|
||||
.poll(() => document.querySelector(uiSelector))
|
||||
.not.toBeNull();
|
||||
});
|
||||
|
||||
it('should mount when an anchor is dynamically added and unmount when an anchor is removed', async () => {
|
||||
const onMount = vi.fn(appendTestApp);
|
||||
const onRemove = vi.fn();
|
||||
|
||||
@@ -355,6 +355,11 @@ function autoMountUi(
|
||||
async function observeElement(selector: string | null | undefined) {
|
||||
let isAnchorExist = !!getAnchor(options);
|
||||
|
||||
// Mount if anchor exists at initialization.
|
||||
if (isAnchorExist) {
|
||||
uiCallbacks.mount();
|
||||
}
|
||||
|
||||
while (!abortController.signal.aborted) {
|
||||
try {
|
||||
const changedAnchor = await waitElement(selector ?? 'body', {
|
||||
|
||||
@@ -67,6 +67,11 @@ export async function createViteBuilder(
|
||||
ignored: [`${wxtConfig.outBaseDir}/**`, `${wxtConfig.wxtDir}/**`],
|
||||
};
|
||||
|
||||
// TODO: Remove once https://github.com/wxt-dev/wxt/pull/1411 is merged
|
||||
config.legacy ??= {};
|
||||
// @ts-ignore: Untyped option:
|
||||
config.legacy.skipWebSocketTokenCheck = true;
|
||||
|
||||
const server = getWxtDevServer?.();
|
||||
|
||||
config.plugins ??= [];
|
||||
|
||||
@@ -217,7 +217,7 @@ function getMainDeclarationEntry(references: WxtDirEntry[]): WxtDirFileEntry {
|
||||
} else if (ref.tsReference) {
|
||||
const absolutePath = resolve(wxt.config.wxtDir, ref.path);
|
||||
const relativePath = relative(wxt.config.wxtDir, absolutePath);
|
||||
lines.push(`/// <reference types="./${normalizePath(relativePath)}" />`);
|
||||
lines.push(`/// <reference path="./${normalizePath(relativePath)}" />`);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { loadConfig } from 'c12';
|
||||
import { resolve as esmResolve } from 'import-meta-resolve';
|
||||
import {
|
||||
InlineConfig,
|
||||
ResolvedConfig,
|
||||
@@ -28,6 +29,7 @@ import { getEslintVersion } from './utils/eslint';
|
||||
import { safeStringToNumber } from './utils/number';
|
||||
import { loadEnv } from './utils/env';
|
||||
import { getPort } from 'get-port-please';
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url';
|
||||
|
||||
/**
|
||||
* Given an inline config, discover the config file if necessary, merge the results, resolve any
|
||||
@@ -50,9 +52,6 @@ export async function resolveConfig(
|
||||
name: 'wxt',
|
||||
cwd: inlineConfig.root ?? process.cwd(),
|
||||
rcFile: false,
|
||||
jitiOptions: {
|
||||
esmResolve: true,
|
||||
},
|
||||
});
|
||||
if (inlineConfig.configFile && metadata.layers?.length === 0) {
|
||||
throw Error(`Config file "${inlineConfig.configFile}" not found`);
|
||||
@@ -84,7 +83,7 @@ export async function resolveConfig(
|
||||
inlineConfig.root ?? userConfig.root ?? process.cwd(),
|
||||
);
|
||||
const wxtDir = path.resolve(root, '.wxt');
|
||||
const wxtModuleDir = await resolveWxtModuleDir();
|
||||
const wxtModuleDir = resolveWxtModuleDir();
|
||||
const srcDir = path.resolve(root, mergedConfig.srcDir ?? root);
|
||||
const entrypointsDir = path.resolve(
|
||||
srcDir,
|
||||
@@ -156,6 +155,7 @@ export async function resolveConfig(
|
||||
}
|
||||
|
||||
const userModules = await resolveWxtUserModules(
|
||||
root,
|
||||
modulesDir,
|
||||
mergedConfig.modules,
|
||||
);
|
||||
@@ -420,21 +420,22 @@ async function getUnimportEslintOptions(
|
||||
/**
|
||||
* Returns the path to `node_modules/wxt`.
|
||||
*/
|
||||
async function resolveWxtModuleDir() {
|
||||
// TODO: Use this once we're fully running in ESM, see https://github.com/wxt-dev/wxt/issues/277
|
||||
// const url = import.meta.resolve('wxt', import.meta.url);
|
||||
// resolve() returns the "wxt/dist/index.mjs" file, not the package's root
|
||||
// directory, which we want to return from this function.
|
||||
// return path.resolve(fileURLToPath(url), '../..');
|
||||
function resolveWxtModuleDir() {
|
||||
// TODO: Drop the __filename expression once we're fully running in ESM
|
||||
// (see https://github.com/wxt-dev/wxt/issues/277)
|
||||
const importer =
|
||||
typeof __filename === 'string'
|
||||
? pathToFileURL(__filename).href
|
||||
: import.meta.url;
|
||||
|
||||
const requireResolve =
|
||||
globalThis.require?.resolve ??
|
||||
(await import('node:module')).default.createRequire(import.meta.url)
|
||||
.resolve;
|
||||
// TODO: Switch to import.meta.resolve() once the parent argument is unflagged
|
||||
// (e.g. --experimental-import-meta-resolve) and all Node.js versions we support
|
||||
// have it.
|
||||
const url = esmResolve('wxt', importer);
|
||||
|
||||
// resolve() returns the "wxt/dist/index.mjs" file, not the package's root
|
||||
// esmResolve() returns the "wxt/dist/index.mjs" file, not the package's root
|
||||
// directory, which we want to return from this function.
|
||||
return path.resolve(requireResolve('wxt'), '../..');
|
||||
return path.resolve(fileURLToPath(url), '../..');
|
||||
}
|
||||
|
||||
async function isDirMissing(dir: string) {
|
||||
@@ -479,14 +480,20 @@ export async function mergeBuilderConfig(
|
||||
}
|
||||
|
||||
export async function resolveWxtUserModules(
|
||||
root: string,
|
||||
modulesDir: string,
|
||||
modules: string[] = [],
|
||||
): Promise<WxtModuleWithMetadata<any>[]> {
|
||||
const importer = pathToFileURL(path.join(root, 'index.js')).href;
|
||||
|
||||
// Resolve node_modules modules
|
||||
const npmModules = await Promise.all<WxtModuleWithMetadata<any>>(
|
||||
modules.map(async (moduleId) => {
|
||||
// Resolve before importing to allow for a local WXT clone to be
|
||||
// symlinked into a project.
|
||||
const resolvedModulePath = esmResolve(moduleId, importer);
|
||||
const mod: { default: WxtModule<any> } = await import(
|
||||
/* @vite-ignore */ moduleId
|
||||
/* @vite-ignore */ resolvedModulePath
|
||||
);
|
||||
if (mod.default == null) {
|
||||
throw Error('Module missing default export: ' + moduleId);
|
||||
|
||||
@@ -11,8 +11,8 @@ describe('Content Script Utils', () => {
|
||||
it('should return a string containing all the options with defaults applied', () => {
|
||||
const hash = hashContentScriptOptions({ matches: [] });
|
||||
|
||||
expect(hash).toMatchInlineSnapshot(
|
||||
`"[["all_frames",false],["exclude_globs",[]],["exclude_matches",[]],["include_globs",[]],["match_about_blank",false],["match_origin_as_fallback",false],["matches",[]],["run_at","document_idle"],["world","ISOLATED"]]"`,
|
||||
expect(hash).toEqual(
|
||||
'[["all_frames",false],["exclude_globs",[]],["exclude_matches",[]],["include_globs",[]],["match_about_blank",false],["match_origin_as_fallback",false],["matches",[]],["run_at","document_idle"],["world","ISOLATED"]]',
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
OutputAsset,
|
||||
} from '../../../types';
|
||||
import { wxt } from '../../wxt';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
|
||||
const outDir = '/output';
|
||||
const contentScriptOutDir = '/output/content-scripts';
|
||||
@@ -1646,6 +1647,33 @@ describe('Manifest Utils', () => {
|
||||
expect(manifest.sidebar_action).toBeUndefined();
|
||||
expect(manifest.content_scripts).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('manifest_version', () => {
|
||||
it('should ignore and log a warning when someone sets `manifest_version` inside the manifest', async () => {
|
||||
const buildOutput = fakeBuildOutput();
|
||||
const expectedVersion = 2;
|
||||
setFakeWxt({
|
||||
logger: mock(),
|
||||
config: {
|
||||
command: 'build',
|
||||
manifestVersion: expectedVersion,
|
||||
manifest: {
|
||||
manifest_version: 3,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { manifest } = await generateManifest([], buildOutput);
|
||||
|
||||
expect(manifest.manifest_version).toBe(expectedVersion);
|
||||
expect(wxt.logger.warn).toBeCalledTimes(1);
|
||||
expect(wxt.logger.warn).toBeCalledWith(
|
||||
expect.stringContaining(
|
||||
'`manifest.manifest_version` config was set, but ignored',
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('stripPathFromMatchPattern', () => {
|
||||
|
||||
@@ -359,5 +359,63 @@ describe('Detect Dev Changes', () => {
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should detect changes to import files with `?suffix`', () => {
|
||||
const importedPath = '/root/utils/shared.css?inline';
|
||||
const changedPath = '/root/utils/shared.css';
|
||||
const script1 = fakeContentScriptEntrypoint({
|
||||
inputPath: '/root/overlay1.content/index.ts',
|
||||
});
|
||||
const script2 = fakeContentScriptEntrypoint({
|
||||
inputPath: '/root/overlay2.ts',
|
||||
});
|
||||
const script3 = fakeContentScriptEntrypoint({
|
||||
inputPath: '/root/overlay3.content/index.ts',
|
||||
});
|
||||
|
||||
const step1: BuildStepOutput = {
|
||||
entrypoints: script1,
|
||||
chunks: [
|
||||
fakeOutputChunk({
|
||||
moduleIds: [fakeFile(), importedPath],
|
||||
}),
|
||||
],
|
||||
};
|
||||
const step2: BuildStepOutput = {
|
||||
entrypoints: script2,
|
||||
chunks: [
|
||||
fakeOutputChunk({
|
||||
moduleIds: [fakeFile(), fakeFile(), fakeFile()],
|
||||
}),
|
||||
],
|
||||
};
|
||||
const step3: BuildStepOutput = {
|
||||
entrypoints: script3,
|
||||
chunks: [
|
||||
fakeOutputChunk({
|
||||
moduleIds: [importedPath, fakeFile(), fakeFile()],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
const currentOutput: BuildOutput = {
|
||||
manifest: fakeManifest(),
|
||||
publicAssets: [],
|
||||
steps: [step1, step2, step3],
|
||||
};
|
||||
const expected: DevModeChange = {
|
||||
type: 'content-script-reload',
|
||||
cachedOutput: {
|
||||
...currentOutput,
|
||||
steps: [step2],
|
||||
},
|
||||
changedSteps: [step1, step3],
|
||||
rebuildGroups: [script1, script3],
|
||||
};
|
||||
|
||||
const actual = detectDevChanges([changedPath], currentOutput);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -135,14 +135,26 @@ function findEffectedSteps(
|
||||
const changes: BuildStepOutput[] = [];
|
||||
const changedPath = normalizePath(changedFile);
|
||||
|
||||
const isChunkEffected = (chunk: OutputFile): boolean =>
|
||||
// If it's an HTML file with the same path, is is effected because HTML files need to be re-rendered
|
||||
// - fileName is normalized, relative bundle path, "<entrypoint-name>.html"
|
||||
(chunk.type === 'asset' &&
|
||||
changedPath.replace('/index.html', '.html').endsWith(chunk.fileName)) ||
|
||||
// If it's a chunk that depends on the changed file, it is effected
|
||||
// - moduleIds are absolute, normalized paths
|
||||
(chunk.type === 'chunk' && chunk.moduleIds.includes(changedPath));
|
||||
const isChunkEffected = (chunk: OutputFile): boolean => {
|
||||
switch (chunk.type) {
|
||||
// If it's an HTML file with the same path, is is effected because HTML files need to be re-rendered
|
||||
// - fileName is normalized, relative bundle path, "<entrypoint-name>.html"
|
||||
case 'asset': {
|
||||
return changedPath
|
||||
.replace('/index.html', '.html')
|
||||
.endsWith(chunk.fileName);
|
||||
}
|
||||
// If it's a chunk that depends on the changed file, it is effected
|
||||
// - moduleIds are absolute, normalized paths
|
||||
case 'chunk': {
|
||||
const modulePaths = chunk.moduleIds.map((path) => path.split('?')[0]);
|
||||
return modulePaths.includes(changedPath);
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (const step of currentOutput.steps) {
|
||||
const effectedChunk = step.chunks.find((chunk) => isChunkEffected(chunk));
|
||||
|
||||
@@ -49,7 +49,6 @@ export async function importEntrypointFile<T>(path: string): Promise<T> {
|
||||
{
|
||||
cache: false,
|
||||
debug: wxt.config.debug,
|
||||
esmResolve: true,
|
||||
alias: {
|
||||
'webextension-polyfill': resolve(
|
||||
wxt.config.wxtModuleDir,
|
||||
@@ -65,7 +64,7 @@ export async function importEntrypointFile<T>(path: string): Promise<T> {
|
||||
},
|
||||
// Continue using node to load TS files even if `bun run --bun` is detected. Jiti does not
|
||||
// respect the custom transform function when using it's native bun option.
|
||||
experimentalBun: false,
|
||||
tryNative: false,
|
||||
// List of extensions to transform with esbuild
|
||||
extensions: [
|
||||
'.ts',
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import { config } from 'dotenv';
|
||||
import { expand } from 'dotenv-expand';
|
||||
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`,
|
||||
],
|
||||
});
|
||||
return expand(
|
||||
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`,
|
||||
],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,12 @@ export async function generateManifest(
|
||||
icons: discoverIcons(buildOutput),
|
||||
};
|
||||
const userManifest = wxt.config.manifest;
|
||||
if (userManifest.manifest_version) {
|
||||
delete userManifest.manifest_version;
|
||||
wxt.logger.warn(
|
||||
'`manifest.manifest_version` config was set, but ignored. To change the target manifest version, use the `manifestVersion` option or the `--mv2`/`--mv3` CLI flags.\nSee https://wxt.dev/guide/essentials/target-different-browsers.html#target-a-manifest-version',
|
||||
);
|
||||
}
|
||||
|
||||
let manifest = defu(
|
||||
userManifest,
|
||||
|
||||
@@ -21,7 +21,8 @@ export async function registerWxt(
|
||||
): Promise<void> {
|
||||
// Default NODE_ENV environment variable before other packages, like vite, do it
|
||||
// See https://github.com/wxt-dev/wxt/issues/873#issuecomment-2254555523
|
||||
process.env.NODE_ENV ??= command === 'serve' ? 'development' : 'production';
|
||||
process.env.NODE_ENV ??=
|
||||
inlineConfig.mode ?? (command === 'serve' ? 'development' : 'production');
|
||||
|
||||
const hooks = createHooks<WxtHooks>();
|
||||
const config = await resolveConfig(inlineConfig, command);
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
resolveAppConfig,
|
||||
} from '../core/builders/vite/plugins';
|
||||
import { InlineConfig } from '../types';
|
||||
import { vitePlugin as unimportPlugin } from '../builtin-modules/unimport';
|
||||
import { createUnimport } from 'unimport';
|
||||
import UnimportPlugin from 'unimport/unplugin';
|
||||
import { registerWxt, wxt } from '../core/wxt';
|
||||
|
||||
/**
|
||||
@@ -39,9 +38,7 @@ export async function WxtVitest(
|
||||
extensionApiMock(wxt.config),
|
||||
];
|
||||
if (wxt.config.imports !== false) {
|
||||
const unimport = createUnimport(wxt.config.imports);
|
||||
await unimport.init();
|
||||
plugins.push(unimportPlugin(unimport));
|
||||
plugins.push(UnimportPlugin.vite(wxt.config.imports));
|
||||
}
|
||||
|
||||
return plugins;
|
||||
|
||||
@@ -4,7 +4,6 @@ import { UnimportOptions, Import } from 'unimport';
|
||||
import { LogLevel } from 'consola';
|
||||
import type { ContentScriptContext } from './client/content-scripts/content-script-context';
|
||||
import type { PluginVisualizerOptions } from '@aklinker1/rollup-plugin-visualizer';
|
||||
import type { FSWatcher } from 'chokidar';
|
||||
import { ResolvedConfig as C12ResolvedConfig } from 'c12';
|
||||
import { Hookable, NestedHooks } from 'hookable';
|
||||
import type * as Nypm from 'nypm';
|
||||
@@ -1097,7 +1096,7 @@ export interface WxtBuilderServer {
|
||||
/**
|
||||
* Chokidar file watcher instance.
|
||||
*/
|
||||
watcher: FSWatcher;
|
||||
watcher: vite.ViteDevServer['watcher'];
|
||||
on?(event: string, callback: () => void): void;
|
||||
}
|
||||
|
||||
|
||||
Generated
+2613
-2325
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,101 @@
|
||||
packages:
|
||||
- docs
|
||||
- packages/*
|
||||
onlyBuiltDependencies:
|
||||
- esbuild
|
||||
catalog:
|
||||
'@1natsu/wait-element': ^4.1.2
|
||||
'@aklinker1/buildc': ^1.1.4
|
||||
'@aklinker1/check': ^1.4.5
|
||||
'@aklinker1/rollup-plugin-visualizer': 5.12.0
|
||||
'@commitlint/config-conventional': ^19.7.1
|
||||
'@commitlint/types': ^19.5.0
|
||||
'@faker-js/faker': ^9.2.0
|
||||
'@sveltejs/vite-plugin-svelte': ^4.0.0 || ^5.0.0
|
||||
'@types/chrome': ^0.0.280
|
||||
'@types/fs-extra': ^11.0.4
|
||||
'@types/lodash.merge': ^4.6.9
|
||||
'@types/node': ^20.17.6
|
||||
'@types/normalize-path': ^3.0.2
|
||||
'@types/prompts': ^2.4.9
|
||||
'@types/react': ^19.0.1
|
||||
'@types/react-dom': ^19.0.2
|
||||
'@types/webextension-polyfill': ^0.12.1
|
||||
'@vitejs/plugin-react': ^4.3.4
|
||||
'@vitejs/plugin-vue': ^5.2.1
|
||||
'@vitest/coverage-v8': ^3.0.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: ^3.0.2
|
||||
cac: ^6.7.14
|
||||
changelogen: ^0.5.7
|
||||
chokidar: ^4.0.3
|
||||
ci-info: ^4.1.0
|
||||
confbox: ^0.1.8
|
||||
consola: ^3.2.3
|
||||
defu: ^6.1.4
|
||||
dequal: ^2.0.3
|
||||
dotenv: ^16.4.5
|
||||
dotenv-expand: ^12.0.1
|
||||
esbuild: ^0.25.0
|
||||
extract-zip: ^2.0.1
|
||||
fast-glob: ^3.3.2
|
||||
filesize: ^10.1.6
|
||||
fs-extra: ^11.2.0
|
||||
get-port-please: ^3.1.2
|
||||
giget: ^1.2.3
|
||||
happy-dom: ^17.1.8
|
||||
hookable: ^5.5.3
|
||||
import-meta-resolve: ^4.1.0
|
||||
is-wsl: ^3.1.0
|
||||
jiti: ^2.4.2
|
||||
json5: ^2.2.3
|
||||
jszip: ^3.10.1
|
||||
linkedom: ^0.18.5
|
||||
lint-staged: ^15.2.10
|
||||
lodash.merge: ^4.6.2
|
||||
magicast: ^0.3.5
|
||||
markdown-it-footnote: ^4.0.0
|
||||
minimatch: ^10.0.1
|
||||
nano-spawn: ^0.2.0
|
||||
normalize-path: ^3.0.0
|
||||
nypm: ^0.3.12
|
||||
ohash: ^1.1.4
|
||||
open: ^10.1.0
|
||||
ora: ^8.1.1
|
||||
oxlint: ^0.11.1
|
||||
perfect-debounce: ^1.0.0
|
||||
picocolors: ^1.1.1
|
||||
prettier: ^3.3.3
|
||||
prompts: ^2.4.2
|
||||
publint: ^0.2.12
|
||||
publish-browser-extension: ^2.3.0 || ^3.0.0
|
||||
react: ^19.0.0
|
||||
react-dom: ^19.0.0
|
||||
sass: ^1.80.7
|
||||
scule: ^1.3.0
|
||||
sharp: ^0.33.5
|
||||
simple-git-hooks: ^2.11.1
|
||||
solid-js: ^1.9.4
|
||||
tsx: 4.19.3
|
||||
typedoc: ^0.25.4
|
||||
typedoc-plugin-frontmatter: ^1.1.0
|
||||
typedoc-plugin-markdown: 4.0.0-next.23
|
||||
typedoc-vitepress-theme: 1.0.0-next.3
|
||||
typescript: ^5.6.3
|
||||
unbuild: ^3.5.0
|
||||
unimport: ^3.13.1
|
||||
unocss: ^0.64.0 || ^0.65.0 || ^65.0.0 ||^66.0.0
|
||||
vite: ^5.0.0 || ^6.0.0
|
||||
vite-node: ^2.1.4 || ^3.0.0
|
||||
vite-plugin-solid: ^2.11.6
|
||||
vitepress: ^1.6.3
|
||||
vitepress-knowledge: ^0.4.0
|
||||
vitest: ^3.0.7
|
||||
vitest-mock-extended: ^3.0.1
|
||||
vitest-plugin-random-seed: ^1.1.1
|
||||
vue: ^3.5.12
|
||||
web-ext-run: ^0.2.1
|
||||
webextension-polyfill: ^0.12.0
|
||||
|
||||
-9
@@ -23,15 +23,6 @@ a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user