Compare commits

...

18 Commits

Author SHA1 Message Date
GitHub Actions b7e2aa3d8f chore(release): v0.13.2 2024-01-01 16:06:12 +00:00
冯不游 e347f4529f feat: Add isolateEvents option to createContentScripUi (#313)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-01-01 10:01:33 -06:00
李志博 3d9683418d Upload a Chinese dubbing plugin for Youtube. (#314)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-01-01 09:45:44 -06:00
Aaron bdce363eed chore: Re-enable coverage (#312) 2023-12-29 17:28:35 -06:00
Aaron e7775f291a docs: Use example tags to automate relevant example lists (#311) 2023-12-29 17:25:46 -06:00
Aaron 59f6a28c65 chore: Upgrade template dependencies (#310) 2023-12-29 12:25:13 -06:00
Aaron f7534464bc chore: Update templates to ^0.13.0 (#309) 2023-12-29 12:14:05 -06:00
Aaron 01445fb1da docs: Add example for setting up custom panels/panes in devtools (#308) 2023-12-29 12:08:33 -06:00
Aaron Klinker 1360eb7c01 docs: Update content script entrypoint docs 2023-12-29 02:01:53 -06:00
Aaron Klinker c99a281169 docs: Update unlisted pages/scripts description 2023-12-29 01:54:39 -06:00
Aaron Klinker 76e63e24c0 docs: Remove duplicate entrypoints/ path 2023-12-29 01:51:26 -06:00
GitHub Actions f5ba1173da chore(release): v0.13.1 2023-12-29 07:39:32 +00:00
Aaron 12079e6ffc chore: Update scripts/build.ts show current build step in progress, not completed count (#306) 2023-12-29 01:21:18 -06:00
Aaron ff6740d429 fix: Ship vite/client types internally for proper resolution using PNPM (#304) 2023-12-29 01:21:05 -06:00
Aaron e6657cb533 fix(storage): Support multiple : characters in storage keys (#303) 2023-12-29 00:40:47 -06:00
Aaron Klinker 2ad099bf7e docs: General fixes and improvements 2023-12-27 12:32:59 -06:00
Aaron Klinker 6421ab34a4 docs: Reorder guide 2023-12-27 12:32:45 -06:00
Aaron Klinker 8919c4015a Update changelog 2023-12-27 11:07:57 -06:00
34 changed files with 233 additions and 107 deletions
+45 -1
View File
@@ -1,5 +1,49 @@
# Changelog
## v0.13.2
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.13.1...v0.13.2)
### 🚀 Enhancements
- Add `isolateEvents` option to `createContentScripUi` ([#313](https://github.com/wxt-dev/wxt/pull/313))
### 📖 Documentation
- Remove duplicate `entrypoints/` path ([76e63e2](https://github.com/wxt-dev/wxt/commit/76e63e2))
- Update unlisted pages/scripts description ([c99a281](https://github.com/wxt-dev/wxt/commit/c99a281))
- Update content script entrypoint docs ([1360eb7](https://github.com/wxt-dev/wxt/commit/1360eb7))
- Add example for setting up custom panels/panes in devtools ([#308](https://github.com/wxt-dev/wxt/pull/308))
- Use example tags to automate relevant example lists ([#311](https://github.com/wxt-dev/wxt/pull/311))
### 🏡 Chore
- Update templates to `^0.13.0` ([#309](https://github.com/wxt-dev/wxt/pull/309))
- Upgrade template dependencies ([#310](https://github.com/wxt-dev/wxt/pull/310))
- Re-enable coverage ([#312](https://github.com/wxt-dev/wxt/pull/312))
### ❤️ Contributors
- 冯不游
## v0.13.1
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.13.0...v0.13.1)
### 🩹 Fixes
- **storage:** Support multiple `:` characters in storage keys ([#303](https://github.com/wxt-dev/wxt/pull/303))
- Ship `vite/client` types internally for proper resolution using PNPM ([#304](https://github.com/wxt-dev/wxt/pull/304))
### 📖 Documentation
- Reorder guide ([6421ab3](https://github.com/wxt-dev/wxt/commit/6421ab3))
- General fixes and improvements ([2ad099b](https://github.com/wxt-dev/wxt/commit/2ad099b))
### 🏡 Chore
- Update `scripts/build.ts` show current build step in progress, not completed count ([#306](https://github.com/wxt-dev/wxt/pull/306))
## v0.13.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.12.5...v0.13.0)
@@ -10,7 +54,7 @@
#### ⚠️ Breaking Changes
- ⚠️ New `wxt/storage` APIs ([#300](https://github.com/wxt-dev/wxt/pull/300))
- `wxt/storage` no longer relies on [`unstorage`](https://www.npmjs.com/package/unstorage). Some `unstorage` APIs, like `prefixStorage`, have been removed, while others, like `snapshot`, are methods on the new `storage` object. Most of the standard usage remains the same. See https://wxt.dev/guide/storage and https://wxt.dev/api/wxt/storage/ for more details ([#300](https://github.com/wxt-dev/wxt/pull/300))
## v0.12.5
+2 -3
View File
@@ -9,9 +9,8 @@
<a href="https://www.npmjs.com/package/wxt" target="_blank"><img alt="npm" src="https://img.shields.io/npm/dm/wxt?labelColor=black&color=%234fa048"></a>
<span> </span>
<a href="https://github.com/wxt-dev/wxt/blob/main/LICENSE" target="_blank"><img alt="NPM" src="https://img.shields.io/npm/l/wxt?labelColor=black&color=%234fa048"></a>
<!-- Hide code coverage while it's broken -->
<!-- <span> </span>
<a href="https://codecov.io/github/wxt-dev/wxt" target="_blank"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/wxt-dev/wxt?labelColor=black&color=%234fa048"></a> -->
<span> </span>
<a href="https://codecov.io/github/wxt-dev/wxt" target="_blank"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/wxt-dev/wxt?labelColor=black&color=%234fa048"></a>
</p>
<p align="center">
@@ -0,0 +1,34 @@
<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue';
const props = defineProps<{
tag?: string;
}>();
const examples = ref();
onMounted(async () => {
const res = await fetch(
'https://raw.githubusercontent.com/wxt-dev/wxt-examples/main/examples.json',
);
examples.value = await res.json();
});
const filteredExamples = computed(() => {
if (props.tag == null) return examples.value;
return examples.value.filter((example) => {
return example.tags?.includes(props.tag);
});
});
</script>
<template>
<ul>
<li v-if="examples == null">Loading...</li>
<template v-else>
<li v-for="example of filteredExamples">
<a :href="example.url" target="_blank">{{ example.name }}</a>
</li>
</template>
</ul>
</template>
@@ -5,6 +5,10 @@ import useListExtensionDetails, {
} from '../composables/useListExtensionDetails';
// Add extension IDs here. Order doesn't matter, will be sorted by weekly active users
// During the transition from chrome.google.com/webstore to
// chromewebstore.google.com, queue.wxt.dev might return null for your
// extension. If it does, use "<slug>/<id>" instead of just the ID. The slug
// can be retrieved from the URL of the item on chromewebstore.google.com
const chromeExtensionIds = [
'ocfdgncpifmegplaglcnglhioflaimkd', // GitHub: Better Line Counts
'mgmdkjcljneegjfajchedjpdhbadklcf', // Anime Skip Player
@@ -12,6 +16,7 @@ const chromeExtensionIds = [
'elfaihghhjjoknimpccccmkioofjjfkf', // StayFree - Website Blocker & Web Analytics
'okifoaikfmpfcamplcfjkpdnhfodpkil', // Doozy: Ai Made Easy
'lknmjhcajhfbbglglccadlfdjbaiifig', // tl;dv - Record, Transcribe & ChatGPT for Google Meet
'youtube中文配音/oglffgiaiekgeicdgkdlnlkhliajdlja', // Youtube中文配音
];
const { data } = useListExtensionDetails(chromeExtensionIds);
@@ -24,6 +29,7 @@ const sortedExtensions = computed(() => {
// Sort based on the user count weighted by the rating
sortKey: ((item.rating ?? 5) / 5) * item.weeklyActiveUsers,
}))
.filter((item) => !!item)
.sort((l, r) => r.sortKey - l.sortKey);
});
+5 -5
View File
@@ -84,18 +84,18 @@ export default defineConfig({
{ text: 'Installation', link: '/guide/installation.md' },
{ text: 'Configuration', link: '/guide/configuration.md' },
{ text: 'Entrypoints', link: '/guide/entrypoints.md' },
{ text: 'Assets', link: '/guide/assets.md' },
{ text: 'Multiple Browsers', link: '/guide/multiple-browsers.md' },
{ text: 'Publishing', link: '/guide/publishing.md' },
{ text: 'Auto-imports', link: '/guide/auto-imports.md' },
{ text: 'Manifest.json', link: '/guide/manifest.md' },
{ text: 'Extension APIs', link: '/guide/extension-apis.md' },
{ text: 'Storage', link: '/guide/storage.md' },
{ text: 'Assets', link: '/guide/assets.md' },
{ text: 'Content Script UI', link: '/guide/content-script-ui.md' },
{ text: 'Multiple Browsers', link: '/guide/multiple-browsers.md' },
{ text: 'Auto-imports', link: '/guide/auto-imports.md' },
{ text: 'Vite', link: '/guide/vite.md' },
{ text: 'Remote Code', link: '/guide/remote-code.md' },
{ text: 'Publishing', link: '/guide/publishing.md' },
{ text: 'Development', link: '/guide/development.md' },
{ text: 'Testing', link: '/guide/testing.md' },
{ text: 'Vite', link: '/guide/vite.md' },
],
},
{
+2
View File
@@ -2,6 +2,7 @@ import DefaultTheme from 'vitepress/theme';
import Icon from '../components/Icon.vue';
import EntrypointPatterns from '../components/EntrypointPatterns.vue';
import UsingWxtSection from '../components/UsingWxtSection.vue';
import ExampleList from '../components/ExampleList.vue';
import './custom.css';
export default {
@@ -10,5 +11,6 @@ export default {
ctx.app.component('Icon', Icon);
ctx.app.component('EntrypointPatterns', EntrypointPatterns);
ctx.app.component('UsingWxtSection', UsingWxtSection);
ctx.app.component('ExampleList', ExampleList);
},
};
+4 -2
View File
@@ -20,7 +20,7 @@ When creating content script entrypoints, they are automatically included in the
```ts
export default defineContentScript({
// Set manifest options
matches: ['*://google.com/*', '*://duckduckgo.com/*'],
matches: string[],
excludeMatches: undefined | [],
includeGlobs: undefined | [],
excludeGlobs: undefined | [],
@@ -90,7 +90,7 @@ To include CSS with your content script, import the CSS file at the top of your
```
<srcDir>
<srcDir>/
└─ entrypoints/
└─ overlay.content/
├─ index.ts
@@ -137,3 +137,5 @@ export default defineContentScript({
},
});
```
See [Content Script UI](/guide/content-script-ui) for more info on creating UIs and including CSS in content scripts.
+10 -3
View File
@@ -13,15 +13,12 @@
## Definition
Plain old HTML file.
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
<!-- Set include/exclude if the page should be removed from some builds -->
<meta name="manifest.include" content="['chrome', ...]" />
<meta name="manifest.exclude" content="['chrome', ...]" />
@@ -31,3 +28,13 @@ Plain old HTML file.
</body>
</html>
```
## Adding UI Elements
Chrome extensions allow you to add panels and side panes to the devtools window.
![DevTools window showing Elements panel and Styles sidebar pane.](https://developer.chrome.com/static/docs/extensions/how-to/devtools/extend-devtools/image/devtools-window-showing-e-9051f7f0347cd_1920.png)
See the WXT's examples for a full walkthrough of extending the devtools window:
<ExampleList tag="devtools" />
+4 -4
View File
@@ -10,10 +10,10 @@ Firefox does not support sandboxed pages.
<EntrypointPatterns
:patterns="[
['entrypoints/sandbox.html', 'sandbox.html'],
['entrypoints/sandbox/index.html', 'sandbox.html'],
['entrypoints/<name>.sandbox.html', '<name>.html` '],
['entrypoints/<name>.sandbox/index.html', '<name>.html` '],
['sandbox.html', 'sandbox.html'],
['sandbox/index.html', 'sandbox.html'],
['<name>.sandbox.html', '<name>.html` '],
['<name>.sandbox/index.html', '<name>.html` '],
]"
/>
+4 -4
View File
@@ -10,10 +10,10 @@ Chrome added support for sidepanels in Manifest V3, they are not available in Ma
<EntrypointPatterns
:patterns="[
['entrypoints/sidepanel.html', 'sidepanel.html'],
['entrypoints/sidepanel/index.html', 'sidepanel.html'],
['entrypoints/<name>.sidepanel.html', '<name>.html` '],
['entrypoints/<name>.sidepanel/index.html', '<name>.html` '],
['sidepanel.html', 'sidepanel.html'],
['sidepanel/index.html', 'sidepanel.html'],
['<name>.sidepanel.html', '<name>.html` '],
['<name>.sidepanel/index.html', '<name>.html` '],
]"
/>
+1 -1
View File
@@ -1,6 +1,6 @@
# Unlisted Pages
HTML pages that are built by Vite, but are not included in the manifest.
HTML pages that are bundled and shipped with the extension, but are not included in the manifest.
### Examples
+1 -1
View File
@@ -1,6 +1,6 @@
# Unlisted Scripts
TypeScript files that are built, but are not included in the manifest.
TypeScript files that are bundled and shipped with the extension, but are not included in the manifest.
You are responsible for loading/running these scripts where needed.
+1 -21
View File
@@ -2,26 +2,6 @@
Simple walkthroughs to accomplish common tasks or patterns with WXT.
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
const examples = ref()
onMounted(async () => {
const res = await fetch("https://raw.githubusercontent.com/wxt-dev/wxt-examples/main/examples.json");
examples.value = await res.json();
})
</script>
<ul>
<li v-if="examples == null">
Loading...
</li>
<template v-else>
<li v-for="example of examples">
<a :href="example.url" target="_blank">{{ example.name }}</a>
</li>
</template>
</ul>
<ExampleList />
> Full code available at [`wxt-dev/wxt-examples`](https://github.com/wxt-dev/wxt-examples)
+10 -12
View File
@@ -51,12 +51,6 @@ export default defineConfig({
});
```
## Vite Config
[Vite](https://vitejs.dev/) is the bundler used to build each entrypoint of your extension. Vite can be configured via the `vite` option.
See [Vite's documentation](https://vitejs.dev/config/) for configuring the bundler.
## Frontend Frameworks
Adding a framework like Vue, React, or Svelte is easy!
@@ -70,9 +64,9 @@ import { defineConfig } from 'wxt';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
vite: {
vite: () => ({
plugins: [vue()],
},
}),
});
```
@@ -81,9 +75,9 @@ import { defineConfig } from 'wxt';
import react from '@vitejs/plugin-react';
export default defineConfig({
vite: {
vite: () => ({
plugins: [react()],
},
}),
});
```
@@ -92,10 +86,14 @@ import { defineConfig } from 'wxt';
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
vite: {
vite: () => ({
plugins: [svelte()],
},
}),
});
```
:::
:::info
Internally, WXT runs `vite build` multiple times during a single build. It can't share the same instance of some plugins between each build, so a function is used to return completely new instances of each plugin for each build.
:::
+6 -6
View File
@@ -6,11 +6,11 @@ There are three ways to mount a UI inside a content script:
Each has their own set of advantages and disadvantages.
| Method | Isolated Styles | HMR | Use page's context |
| ---------- | :-------------: | :-: | :----------------: |
| Integrated | ❌ | ❌ | ✅ |
| ShadowRoot | ✅ | ❌ | ✅ |
| IFrame | ✅ | ✅ | ❌ |
| Method | Isolated Styles | Isolated Events | HMR | Use page's context |
| ---------- | :-------------: | :-----------------: | :-: | :----------------: |
| Integrated | ❌ | ❌ | ❌ | ✅ |
| ShadowRoot | ✅ | ✅ (off by default) | ❌ | ✅ |
| IFrame | ✅ | ✅ | ✅ | ❌ |
## Integrated
@@ -149,7 +149,7 @@ export default defineContentScript({
Often in web extensions, you don't want your content script's CSS affecting the page, or vise-versa. The [`ShadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot) API is ideal for this.
WXT provides a helper function, [`createContentScriptUi`](/api/wxt/client/functions/createContentScriptUi), that abstracts all the `ShadowRoot` setup away, making it easy to create UIs with isolated CSS.
WXT provides a helper function, [`createContentScriptUi`](/api/wxt/client/functions/createContentScriptUi), that abstracts all the `ShadowRoot` setup away, making it easy to create UIs with isolated CSS. It also supports an optional `isolateEvents` parameter to further isolate user interactions.
To use `createContentScriptUi`, follow these steps:
+6 -1
View File
@@ -1,12 +1,13 @@
# Manifest.json
The manifest.json is generated at build-time based on files in your `entrypoints` directory and your `wxt.config.ts`.
The manifest.json is generated at build-time based on files in the `entrypoints/` directory and `wxt.config.ts`.
## Configuration
While entrypoints are generated and added to the manifest at build-time, you can customize or add to your `manifest.json` in the config file.
```ts
// wxt.config.tsentrypoint of your extension
import { defineConfig } from 'wxt';
export default defineConfig({
@@ -118,3 +119,7 @@ export default defineConfig({
},
});
```
See the official localization examples for more details:
<ExampleList tag="i18n" />
+1 -1
View File
@@ -4,7 +4,7 @@ WXT offers several utilities that simplify the publishing process.
## First Time Publishing
If you're publishing an extension to a store for the first time, it's recommended that you manually navigate the process. Each store has unique steps and requirements that you need to familiarize yourself with.
If you're publishing an extension to a store for the first time, you must manually navigate the process. Each store has unique steps and requirements that you need to familiarize yourself with.
Each store requires that a ZIP file be uploaded. You can generate these using the `wxt zip` command:
+1 -3
View File
@@ -6,9 +6,7 @@ WXT officially supports [Vitest](https://vitest.dev/) for unit tests and either
For details setting up each testing framework, see the official examples:
- [Vitest example](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-vitest#readme)
- [Playwright example](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-playwright#readme)
- [Puppeteer example](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-puppeteer#readme)
<ExampleList tag="testing" />
### Unofficial Frameworks
+2 -2
View File
@@ -44,7 +44,7 @@ describe('Auto Imports', () => {
".wxt/wxt.d.ts
----------------------------------------
// Generated by wxt
/// <reference types="vite/client" />
/// <reference types="wxt/vite-builder-env" />
/// <reference types="./types/imports.d.ts" />
/// <reference types="./types/paths.d.ts" />
/// <reference types="./types/i18n.d.ts" />
@@ -83,7 +83,7 @@ describe('Auto Imports', () => {
".wxt/wxt.d.ts
----------------------------------------
// Generated by wxt
/// <reference types="vite/client" />
/// <reference types="wxt/vite-builder-env" />
/// <reference types="./types/paths.d.ts" />
/// <reference types="./types/i18n.d.ts" />
/// <reference types="./types/globals.d.ts" />
+1 -1
View File
@@ -227,7 +227,7 @@ describe('TypeScript Project', () => {
".wxt/wxt.d.ts
----------------------------------------
// Generated by wxt
/// <reference types="vite/client" />
/// <reference types="wxt/vite-builder-env" />
/// <reference types="./types/imports.d.ts" />
/// <reference types="./types/paths.d.ts" />
/// <reference types="./types/i18n.d.ts" />
+6 -3
View File
@@ -1,7 +1,7 @@
{
"name": "wxt",
"type": "module",
"version": "0.13.0",
"version": "0.13.2",
"description": "Next gen framework for developing web extensions",
"engines": {
"node": ">=18",
@@ -76,6 +76,9 @@
"types": "./dist/storage.d.cts",
"default": "./dist/storage.cjs"
}
},
"./vite-builder-env": {
"types": "./dist/vite-builder-env.d.ts"
}
},
"scripts": {
@@ -90,7 +93,7 @@
"compile:wxt": "tsc --noEmit",
"compile:virtual": "tsc --noEmit -p src/virtual",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"test:coverage": "vitest run --coverage.enabled \"--coverage.include=src/**\" \"--coverage.exclude=src/core/utils/testing/**\" \"--coverage.exclude=**/*.d.ts\"",
"prepare": "simple-git-hooks",
"prepublish": "pnpm -s build",
"docs:gen": "typedoc --options docs/typedoc.json",
@@ -102,7 +105,7 @@
"dependencies": {
"@types/webextension-polyfill": "^0.10.5",
"@webext-core/fake-browser": "^1.3.1",
"@webext-core/isolated-element": "^1.0.4",
"@webext-core/isolated-element": "^1.1.1",
"@webext-core/match-patterns": "^1.0.3",
"async-mutex": "^0.4.0",
"c12": "^1.5.1",
+4 -4
View File
@@ -15,8 +15,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1
'@webext-core/isolated-element':
specifier: ^1.0.4
version: 1.0.4
specifier: ^1.1.1
version: 1.1.1
'@webext-core/match-patterns':
specifier: ^1.0.3
version: 1.0.3
@@ -1413,8 +1413,8 @@ packages:
lodash.merge: 4.6.2
dev: false
/@webext-core/isolated-element@1.0.4:
resolution: {integrity: sha512-jbkG+7b6Ty4fNo2o53rokCTkNRinI/0tneJSyuUCJfPzAFtyylF3IxH/WhXykXC+1Ca8ouQnjbEcpYt9IFNcUg==}
/@webext-core/isolated-element@1.1.1:
resolution: {integrity: sha512-kn5OURB8FaEB0oSZdf1jc1PyohWXbWQbdhXfAS2d3AxxkP8HlYfhB75fhZJ3GceZvFf8in4bZNJbOvcArSFxCg==}
dev: false
/@webext-core/match-patterns@1.0.3:
+6 -3
View File
@@ -29,9 +29,9 @@ const preset = {
} satisfies tsup.Options;
function spinnerPMap(configs: tsup.Options[]) {
let completed = 0;
let progress = 1;
const updateSpinner = () => {
spinner.text = `${spinnerText} [${completed}/${configs.length}]`;
spinner.text = `${spinnerText} [${progress}/${configs.length}]`;
};
updateSpinner();
@@ -39,7 +39,7 @@ function spinnerPMap(configs: tsup.Options[]) {
config,
async (config) => {
const res = await tsup.build(config);
completed++;
progress++;
updateSpinner();
return res;
},
@@ -106,6 +106,9 @@ await spinnerPMap(config).catch((err) => {
process.exit(1);
});
// Copy "public" files that need shipped inside WXT
await fs.copyFile('src/vite-builder-env.d.ts', 'dist/vite-builder-env.d.ts');
spinner.clear().stop();
const duration = Date.now() - startTime;
+9
View File
@@ -22,6 +22,15 @@ describe('Storage Utils', () => {
expect(actual).toBe(expected);
});
it('should return the value if multiple : are use in the key', async () => {
const expected = 'value';
await fakeBrowser.storage[storageArea].set({ 'some:key': expected });
const actual = await storage.getItem(`${storageArea}:some:key`);
expect(actual).toBe(expected);
});
it("should return null if the value doesn't exist", async () => {
const actual = await storage.getItem(`${storageArea}:count`);
@@ -5,6 +5,7 @@ import { ContentScriptContext } from '~/client/content-scripts/content-script-co
import { createIsolatedElement } from '@webext-core/isolated-element';
import { mock } from 'vitest-mock-extended';
import { browser } from '~/browser';
import { faker } from '@faker-js/faker';
vi.mock('@webext-core/isolated-element', async () => {
const { vi } = await import('vitest');
@@ -332,4 +333,26 @@ describe('createContentScriptUi', () => {
expect(document.querySelector('test-app')).toBeDefined();
});
});
it('should forward isolateEvents into createIsolatedElement', async () => {
const isolateEvents = faker.helpers.arrayElement([
undefined,
true,
false,
['click', 'keydown'],
]);
await createContentScriptUi(createCtx(), {
name: 'test-app',
type: 'inline',
mount: testApp,
isolateEvents,
});
expect(createIsolatedElementMock).toBeCalledTimes(1);
expect(createIsolatedElementMock).toBeCalledWith(
expect.objectContaining({
isolateEvents,
}),
);
});
});
@@ -10,8 +10,8 @@ import {
} from '../utils/content-script-ui';
/**
* Utility for mounting content script UI's with isolated styles. Automatically removed from the DOM
* when the content script's context is invalidated.
* Utility for mounting content script UI's with isolated styles and controlled event bubbling.
* Automatically removed from the DOM when the content script's context is invalidated.
*
* See https://wxt.dev/guide/content-script-ui.html for full documentation.
*
@@ -31,7 +31,7 @@ import {
* const app = document.createElement("div");
* app.textContent = "Content Script UI";
* container.append(app);
* }
* },
* })
* ui.mount();
* }
@@ -56,6 +56,7 @@ export async function createContentScriptUi<TApp>(
textContent: css.join('\n').trim(),
},
mode: 'open',
isolateEvents: options.isolateEvents,
});
let mounted: TApp;
@@ -170,4 +171,13 @@ export type ContentScriptUiOptions<TApp> = ContentScriptPositioningOptions &
* See https://wxt.dev/guide/content-script-ui.html for more info.
*/
css?: string;
/**
* When enabled, `event.stopPropagation` will be called on events trying to bubble out of the
* shadow root.
*
* - Set to `true` to stop the propagation of a default set of events,
* `["keyup", "keydown", "keypress"]`
* - Set to an array of event names to stop the propagation of a custom list of events
*/
isolateEvents?: boolean | string[];
};
+1 -1
View File
@@ -180,7 +180,7 @@ async function writeMainDeclarationFile(
filePath,
[
'// Generated by wxt',
`/// <reference types="vite/client" />`,
`/// <reference types="wxt/vite-builder-env" />`,
...references.map(
(ref) =>
`/// <reference types="./${normalizePath(relative(dir, ref))}" />`,
+3 -1
View File
@@ -26,7 +26,9 @@ function createStorage(): WxtStorage {
return driver;
};
const resolveKey = (key: string) => {
const [driverArea, driverKey] = key.split(':', 2);
const deliminatorIndex = key.indexOf(':');
const driverArea = key.substring(0, deliminatorIndex);
const driverKey = key.substring(deliminatorIndex + 1);
if (driverKey == null)
throw Error(
`Storage key should be in the form of "area:key", but recieved "${key}"`,
+1
View File
@@ -0,0 +1 @@
/// <reference types="vite/client" />
+4 -4
View File
@@ -19,10 +19,10 @@
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
"@vitejs/plugin-react": "^4.2.1",
"typescript": "^5.3.2",
"wxt": "^0.12.0"
"typescript": "^5.3.3",
"wxt": "^0.13.0"
}
}
+3 -3
View File
@@ -15,11 +15,11 @@
"postinstall": "wxt prepare"
},
"dependencies": {
"solid-js": "^1.7.8"
"solid-js": "^1.8.7"
},
"devDependencies": {
"typescript": "^5.3.2",
"typescript": "^5.3.3",
"vite-plugin-solid": "^2.8.0",
"wxt": "^0.12.0"
"wxt": "^0.13.0"
}
}
+7 -7
View File
@@ -14,12 +14,12 @@
"postinstall": "wxt prepare"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tsconfig/svelte": "^5.0.0",
"svelte": "^4.0.5",
"svelte-check": "^3.4.6",
"tslib": "^2.6.0",
"typescript": "^5.3.2",
"wxt": "^0.12.0"
"@sveltejs/vite-plugin-svelte": "^3.0.1",
"@tsconfig/svelte": "^5.0.2",
"svelte": "^4.2.8",
"svelte-check": "^3.6.2",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
"wxt": "^0.13.0"
}
}
+2 -2
View File
@@ -15,7 +15,7 @@
"postinstall": "wxt prepare"
},
"devDependencies": {
"typescript": "^5.3.2",
"wxt": "^0.12.0"
"typescript": "^5.3.3",
"wxt": "^0.13.0"
}
}
+5 -5
View File
@@ -15,12 +15,12 @@
"postinstall": "wxt prepare"
},
"dependencies": {
"vue": "^3.3.4"
"vue": "^3.4.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.5.1",
"typescript": "^5.3.2",
"vue-tsc": "^1.8.25",
"wxt": "^0.12.0"
"@vitejs/plugin-vue": "^5.0.1",
"typescript": "^5.3.3",
"vue-tsc": "^1.8.27",
"wxt": "^0.13.0"
}
}