Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f2d3061e97 | |||
| 760c34e416 | |||
| 48398b315c | |||
| 45d0d9d7f1 | |||
| b0f4ac8221 | |||
| 719192b1aa | |||
| 7eb32bdac8 | |||
| 862756fd5b | |||
| 5ba16e72e0 | |||
| e43ae0504d | |||
| acb6cd180c |
@@ -70,6 +70,8 @@ const chromeExtensionIds = [
|
||||
'hafcajcllbjnoolpfngclfmmgpikdhlm', // Monochromate
|
||||
'bmoggiinmnodjphdjnmpcnlleamkfedj', // AliasVault - Open-Source Password & (Email) Alias Manager
|
||||
'hlnhhamckimoaiekbglafiebkfimhapb', // SnapThePrice: AI-Powered Real-time Lowest Price Finder
|
||||
'gdjampjdgjmbifnhldgcnccdjkcoicmg', // radiofrance - news & broadcasts (French), music (international)
|
||||
'jlnhphlghikichhgbnkepenehbmloenb', // Blens - Time Tracker and AI Insight
|
||||
];
|
||||
|
||||
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
|
||||
|
||||
@@ -14,7 +14,7 @@ You can configure browser startup in 3 places:
|
||||
|
||||
1. `<rootDir>/web-ext.config.ts`: Ignored from version control, this file lets you configure your own options for a specific project without affecting other developers
|
||||
|
||||
```ts
|
||||
```ts [web-ext.config.ts]
|
||||
import { defineWebExtConfig } from 'wxt';
|
||||
|
||||
export default defineWebExtConfig({
|
||||
@@ -22,7 +22,7 @@ You can configure browser startup in 3 places:
|
||||
});
|
||||
```
|
||||
|
||||
2. `<rootDir>/wxt.config.ts`: Via the [`runner` config](/api/reference/wxt/interfaces/InlineConfig#runner), included in version control
|
||||
2. `<rootDir>/wxt.config.ts`: Via the [`webExt` config](/api/reference/wxt/interfaces/InlineConfig#webext), included in version control
|
||||
3. `$HOME/web-ext.config.ts`: Provide default values for all WXT projects on your computer
|
||||
|
||||
## Recipes
|
||||
@@ -31,7 +31,7 @@ You can configure browser startup in 3 places:
|
||||
|
||||
To set or customize the browser opened during development:
|
||||
|
||||
```ts
|
||||
```ts [web-ext.config.ts]
|
||||
export default defineWebExtConfig({
|
||||
binaries: {
|
||||
chrome: '/path/to/chrome-beta', // Use Chrome Beta instead of regular Chrome
|
||||
@@ -81,7 +81,7 @@ You can use any directory you'd like for `--user-data-dir`, the examples above c
|
||||
|
||||
If you prefer to load the extension into your browser manually, you can disable the auto-open behavior:
|
||||
|
||||
```ts
|
||||
```ts [web-ext.config.ts]
|
||||
export default defineWebExtConfig({
|
||||
disabled: true,
|
||||
});
|
||||
|
||||
@@ -211,12 +211,12 @@ When defining your background entrypoint, keep in mind that WXT will import this
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```ts
|
||||
browser.action.onClick.addListener(() => { // [!code --]
|
||||
browser.action.onClicked.addListener(() => { // [!code --]
|
||||
// ... // [!code --]
|
||||
}); // [!code --]
|
||||
|
||||
export default defineBackground(() => {
|
||||
browser.action.onClick.addListener(() => { // [!code ++]
|
||||
browser.action.onClicked.addListener(() => { // [!code ++]
|
||||
// ... // [!code ++]
|
||||
}); // [!code ++]
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ export default defineConfig({
|
||||
analysis: {
|
||||
open: true,
|
||||
},
|
||||
runner: {
|
||||
webExt: {
|
||||
startUrls: ['https://duckduckgo.com'],
|
||||
},
|
||||
example: {
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
# Changelog
|
||||
|
||||
## v0.20.3
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.20.2...wxt-v0.20.3)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Automatically place document-level CSS outside shadow root ([#1594](https://github.com/wxt-dev/wxt/pull/1594))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Fix double hashing of inline script keys ([b0f4ac8](https://github.com/wxt-dev/wxt/commit/b0f4ac8))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.20.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.20.1...wxt-v0.20.2)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Fix hashing issue with inline scripts ([#1591](https://github.com/wxt-dev/wxt/pull/1591))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Fix typo in changelog ([acb6cd1](https://github.com/wxt-dev/wxt/commit/acb6cd1))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Yunsup Sim ([@SimYunSup](https://github.com/SimYunSup))
|
||||
- Aaron ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.20.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.20.0...wxt-v0.20.1)
|
||||
@@ -7,7 +40,7 @@
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Enable wxt usage inside of devcontainers ([#1406](https://github.com/wxt-dev/wxt/pull/1406))
|
||||
- Type-safe `import.meta.env.BROWSER` with new `targetBrowers` config ([#1574](https://github.com/wxt-dev/wxt/pull/1574))
|
||||
- Type-safe `import.meta.env.BROWSER` with new `targetBrowsers` config ([#1574](https://github.com/wxt-dev/wxt/pull/1574))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wxt",
|
||||
"type": "module",
|
||||
"version": "0.20.1",
|
||||
"version": "0.20.3",
|
||||
"description": "⚡ Next-gen Web Extension Framework",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@@ -167,6 +167,10 @@
|
||||
"types": "./dist/utils/match-patterns.d.ts",
|
||||
"default": "./dist/utils/match-patterns.mjs"
|
||||
},
|
||||
"./utils/split-shadow-root-css": {
|
||||
"types": "./dist/utils/split-shadow-root-css.d.ts",
|
||||
"default": "./dist/utils/split-shadow-root-css.mjs"
|
||||
},
|
||||
"./utils/storage": {
|
||||
"types": "./dist/utils/storage.d.ts",
|
||||
"default": "./dist/utils/storage.mjs"
|
||||
|
||||
@@ -85,13 +85,13 @@ export function devHtmlPrerender(
|
||||
inlineScripts.forEach((script) => {
|
||||
// Save the text content for later
|
||||
const textContent = script.textContent ?? '';
|
||||
const textHash = hash(textContent);
|
||||
inlineScriptContents[textHash] = textContent;
|
||||
const key = hash(textContent);
|
||||
inlineScriptContents[key] = textContent;
|
||||
|
||||
// Replace unsafe inline script
|
||||
const virtualScript = document.createElement('script');
|
||||
virtualScript.type = 'module';
|
||||
virtualScript.src = `${server.origin}/@id/${virtualInlineScript}?${textHash}`;
|
||||
virtualScript.src = `${server.origin}/@id/${virtualInlineScript}?${key}`;
|
||||
script.replaceWith(virtualScript);
|
||||
});
|
||||
|
||||
@@ -111,7 +111,7 @@ export function devHtmlPrerender(
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'wxt:virtualize-react-refresh',
|
||||
name: 'wxt:virtualize-inline-scripts',
|
||||
apply: 'serve',
|
||||
resolveId(id) {
|
||||
// Resolve inline scripts
|
||||
@@ -127,9 +127,9 @@ export function devHtmlPrerender(
|
||||
load(id) {
|
||||
// Resolve virtualized inline scripts
|
||||
if (id.startsWith(resolvedVirtualInlineScript)) {
|
||||
// id="virtual:wxt-inline-script?<hash>"
|
||||
const hash = Number(id.substring(id.indexOf('?') + 1));
|
||||
return inlineScriptContents[hash];
|
||||
// id="virtual:wxt-inline-script?<key>"
|
||||
const key = id.substring(id.indexOf('?') + 1);
|
||||
return inlineScriptContents[key];
|
||||
}
|
||||
|
||||
// Ignore chunks during HTML file pre-rendering
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,6 +5,7 @@ import type { ContentScriptUi, ContentScriptUiOptions } from './types';
|
||||
import { createIsolatedElement } from '@webext-core/isolated-element';
|
||||
import { applyPosition, createMountFunctions, mountUi } from './shared';
|
||||
import { logger } from '../internal/logger';
|
||||
import { splitShadowRootCss } from '../split-shadow-root-css';
|
||||
|
||||
/**
|
||||
* Create a content script UI inside a [`ShadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot).
|
||||
@@ -17,6 +18,7 @@ export async function createShadowRootUi<TMounted>(
|
||||
ctx: ContentScriptContext,
|
||||
options: ShadowRootContentScriptUiOptions<TMounted>,
|
||||
): Promise<ShadowRootContentScriptUi<TMounted>> {
|
||||
const instanceId = crypto.randomUUID();
|
||||
const css: string[] = [];
|
||||
|
||||
if (!options.inheritStyles) {
|
||||
@@ -31,6 +33,9 @@ export async function createShadowRootUi<TMounted>(
|
||||
css.push(entryCss.replaceAll(':root', ':host'));
|
||||
}
|
||||
|
||||
// Some rules must be applied outside the shadow root, so split the CSS apart
|
||||
const { shadowCss, documentCss } = splitShadowRootCss(css.join('\n').trim());
|
||||
|
||||
const {
|
||||
isolatedElement: uiContainer,
|
||||
parentElement: shadowHost,
|
||||
@@ -38,7 +43,7 @@ export async function createShadowRootUi<TMounted>(
|
||||
} = await createIsolatedElement({
|
||||
name: options.name,
|
||||
css: {
|
||||
textContent: css.join('\n').trim(),
|
||||
textContent: shadowCss,
|
||||
},
|
||||
mode: options.mode ?? 'open',
|
||||
isolateEvents: options.isolateEvents,
|
||||
@@ -51,6 +56,20 @@ export async function createShadowRootUi<TMounted>(
|
||||
// Add shadow root element to DOM
|
||||
mountUi(shadowHost, options);
|
||||
applyPosition(shadowHost, shadow.querySelector('html'), options);
|
||||
|
||||
// Add document CSS
|
||||
if (
|
||||
documentCss &&
|
||||
!document.querySelector(
|
||||
`style[wxt-shadow-root-document-styles="${instanceId}"]`,
|
||||
)
|
||||
) {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = documentCss;
|
||||
style.setAttribute('wxt-shadow-root-document-styles', instanceId);
|
||||
(document.head ?? document.body).append(style);
|
||||
}
|
||||
|
||||
// Mount UI inside shadow root
|
||||
mounted = options.onMount(uiContainer, shadow, shadowHost);
|
||||
};
|
||||
@@ -58,11 +77,20 @@ export async function createShadowRootUi<TMounted>(
|
||||
const remove = () => {
|
||||
// Cleanup mounted state
|
||||
options.onRemove?.(mounted);
|
||||
|
||||
// Detach shadow root from DOM
|
||||
shadowHost.remove();
|
||||
|
||||
// Remove document CSS
|
||||
const documentStyle = document.querySelector(
|
||||
`style[wxt-shadow-root-document-styles="${instanceId}"]`,
|
||||
);
|
||||
documentStyle?.remove();
|
||||
|
||||
// Remove children from uiContainer
|
||||
while (uiContainer.lastChild)
|
||||
uiContainer.removeChild(uiContainer.lastChild);
|
||||
|
||||
// Clear mounted value
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Given a CSS string that will be loaded into a shadow root, split it into two parts:
|
||||
* - `documentCss`: CSS that needs to be applied to the document (like `@property`)
|
||||
* - `shadowCss`: CSS that needs to be applied to the shadow root
|
||||
* @param css
|
||||
*/
|
||||
export function splitShadowRootCss(css: string): {
|
||||
documentCss: string;
|
||||
shadowCss: string;
|
||||
} {
|
||||
let shadowCss = css;
|
||||
let documentCss = '';
|
||||
|
||||
const rulesRegex = /(\s*@property[\s\S]*?{[\s\S]*?})/gm;
|
||||
let match;
|
||||
while ((match = rulesRegex.exec(css)) !== null) {
|
||||
documentCss += match[1];
|
||||
shadowCss = shadowCss.replace(match[1], '');
|
||||
}
|
||||
|
||||
return {
|
||||
documentCss: documentCss.trim(),
|
||||
shadowCss: shadowCss.trim(),
|
||||
};
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
"src/utils/define-unlisted-script.ts",
|
||||
"src/utils/define-wxt-plugin.ts",
|
||||
"src/utils/match-patterns.ts",
|
||||
"src/utils/split-shadow-root-css.ts",
|
||||
"src/utils/storage.ts",
|
||||
"src/testing/index.ts",
|
||||
"src/modules.ts"
|
||||
|
||||
Reference in New Issue
Block a user