Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5fe4248e2 | |||
| 58140cf3e8 | |||
| 1a39f856af | |||
| 82b769e939 | |||
| e47519fb76 | |||
| 171e32c272 | |||
| 54e5ed0bb4 | |||
| a94d673f31 | |||
| b7f7222c26 | |||
| aa5a9d4fa9 | |||
| 77da2d6ade | |||
| 3119c04e10 | |||
| c09994263e | |||
| 2a4fa9ae5c | |||
| c833d3b15b | |||
| d6e095bfce | |||
| 825160a3cc | |||
| e29ca33f82 | |||
| ca5a52c6f1 | |||
| 982c69f8ae | |||
| 6fc7d9254a | |||
| 2e0e104d48 | |||
| 02430fd7b8 | |||
| 2e6d35d193 | |||
| 7cf412ac1f | |||
| 9398cbb596 | |||
| ca9b96142e | |||
| db57c8e079 |
@@ -1,5 +1,28 @@
|
||||
# Changelog
|
||||
|
||||
## v0.17.12
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.11...v0.17.12)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Add hooks for extending vite config ([#599](https://github.com/wxt-dev/wxt/pull/599))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- **content-script-ui:** Properly assign and unassign mounted value ([#598](https://github.com/wxt-dev/wxt/pull/598))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Add discord server link ([#593](https://github.com/wxt-dev/wxt/pull/593))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Remove unnecssary 'Omit' types ([db57c8e](https://github.com/wxt-dev/wxt/commit/db57c8e))
|
||||
- **deps-dev:** Bump @aklinker1/check from 1.1.1 to 1.2.0 ([#588](https://github.com/wxt-dev/wxt/pull/588))
|
||||
- **deps-dev:** Bump vue from 3.3.10 to 3.4.21 ([#589](https://github.com/wxt-dev/wxt/pull/589))
|
||||
- **deps-dev:** Bump sass from 1.69.5 to 1.72.0 ([#591](https://github.com/wxt-dev/wxt/pull/591))
|
||||
|
||||
## v0.17.11
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.10...v0.17.11)
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
<a href="https://wxt.dev/api/config.html" target="_blank">Configuration</a>
|
||||
•
|
||||
<a href="https://wxt.dev/examples.html" target="_blank">Examples</a>
|
||||
•
|
||||
<a href="https://discord.gg/ZFsZqGery9" target="_blank">Discord</a>
|
||||
</p>
|
||||
|
||||

|
||||
|
||||
@@ -22,6 +22,9 @@ const chromeExtensionIds = [
|
||||
'nomnkbngkijpffepcgbbofhcnafpkiep', // DocVersionRedirector
|
||||
'ceicccfeikoipigeghddpocceifjelph', // Plex Skipper
|
||||
'aelkipgppclpfimeamgmlonimflbhlgf', // GitHub Custom Notifier
|
||||
'djnlaiohfaaifbibleebjggkghlmcpcj', // Fluent Read
|
||||
'nhclljcpfmmaiojbhhnkpjcfmacfcian', // Facebook Video Controls
|
||||
'mblkhbaakhbhiimkbcnmeciblfhmafna', // ElemSnap - Quick capture of webpage elements and conversion to images
|
||||
];
|
||||
|
||||
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
|
||||
|
||||
@@ -146,6 +146,9 @@ export default defineConfig({
|
||||
],
|
||||
},
|
||||
|
||||
socialLinks: [{ icon: 'github', link: 'https://github.com/wxt-dev/wxt' }],
|
||||
socialLinks: [
|
||||
{ icon: 'discord', link: 'https://discord.gg/ZFsZqGery9' },
|
||||
{ icon: 'github', link: 'https://github.com/wxt-dev/wxt' },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -63,7 +63,7 @@ Files in the assets directory will be processed by Vite. They are imported in yo
|
||||
<!-- ... -->
|
||||
</head>
|
||||
<body>
|
||||
<img src="~/illustration.svg" />
|
||||
<img src="~/assets/illustration.svg" />
|
||||
<!-- ... -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -89,7 +89,7 @@ For a full list of entrypoints and each of their options, see the [`/entrypoints
|
||||
|
||||
### Side Effects
|
||||
|
||||
You cannot use imported variables outside the `main` function is JS entrypoints. This includes options, as shown below:
|
||||
You cannot use imported variables outside the `main` function in JS entrypoints. This includes options, as shown below:
|
||||
|
||||
```ts
|
||||
// entrypoints/content.ts
|
||||
|
||||
@@ -39,9 +39,9 @@ Then we can use `browser.storage` to save the install date to local storage.
|
||||
```ts
|
||||
// background.ts
|
||||
export default defineBackground(() => {
|
||||
browser.runtime.onInstall.addEventListener(({ reason }) => {
|
||||
browser.runtime.onInstalled.addListener(({ reason }) => {
|
||||
if (reason === 'install') {
|
||||
browser.storage.local.setItem({ installDate: Date.now() });
|
||||
browser.storage.local.set({ installDate: Date.now() });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ The manifest.json is generated at build-time based on files in the `entrypoints/
|
||||
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
|
||||
// wxt.config.ts entrypoint of your extension
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
|
||||
+16
-3
@@ -9,16 +9,21 @@ const hooks: WxtHooks = {
|
||||
'build:manifestGenerated': vi.fn(),
|
||||
'entrypoints:resolved': vi.fn(),
|
||||
'entrypoints:grouped': vi.fn(),
|
||||
'vite:build:extendConfig': vi.fn(),
|
||||
'vite:devServer:extendConfig': vi.fn(),
|
||||
};
|
||||
|
||||
function expectHooksToBeCalled(called: Record<keyof WxtHooks, boolean>) {
|
||||
function expectHooksToBeCalled(
|
||||
called: Record<keyof WxtHooks, boolean | number>,
|
||||
) {
|
||||
Object.keys(hooks).forEach((key) => {
|
||||
const hookName = key as keyof WxtHooks;
|
||||
const times = called[hookName] ? 1 : 0;
|
||||
const value = called[hookName];
|
||||
const times = typeof value === 'number' ? value : value ? 1 : 0;
|
||||
expect(
|
||||
hooks[hookName],
|
||||
`Expected "${hookName}" to be called ${times} time(s)`,
|
||||
).toBeCalledTimes(called[hookName] ? 1 : 0);
|
||||
).toBeCalledTimes(times);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,6 +45,8 @@ describe('Hooks', () => {
|
||||
'build:manifestGenerated': false,
|
||||
'entrypoints:grouped': false,
|
||||
'entrypoints:resolved': true,
|
||||
'vite:build:extendConfig': false,
|
||||
'vite:devServer:extendConfig': false,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,6 +63,8 @@ describe('Hooks', () => {
|
||||
'build:manifestGenerated': true,
|
||||
'entrypoints:grouped': true,
|
||||
'entrypoints:resolved': true,
|
||||
'vite:build:extendConfig': 1,
|
||||
'vite:devServer:extendConfig': false,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -72,6 +81,8 @@ describe('Hooks', () => {
|
||||
'build:manifestGenerated': true,
|
||||
'entrypoints:grouped': true,
|
||||
'entrypoints:resolved': true,
|
||||
'vite:build:extendConfig': 1,
|
||||
'vite:devServer:extendConfig': false,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -94,6 +105,8 @@ describe('Hooks', () => {
|
||||
'build:manifestGenerated': true,
|
||||
'entrypoints:grouped': true,
|
||||
'entrypoints:resolved': true,
|
||||
'vite:build:extendConfig': 2,
|
||||
'vite:devServer:extendConfig': 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -272,7 +272,7 @@ describe('Output Directory Structure', () => {
|
||||
.toMatchInlineSnapshot(`
|
||||
".output/chrome-mv3/background.js
|
||||
----------------------------------------
|
||||
import { l as logHello } from "./chunks/log-bezs0tt4.js";
|
||||
import { l as logHello } from "./chunks/log-BsZv2eRn.js";
|
||||
function defineBackground(arg) {
|
||||
if (typeof arg === "function")
|
||||
return { main: arg };
|
||||
@@ -362,11 +362,13 @@ describe('Output Directory Structure', () => {
|
||||
function logHello(name) {
|
||||
console.log(\`Hello \${name}!\`);
|
||||
}
|
||||
_background;
|
||||
const definition = defineBackground({
|
||||
main() {
|
||||
logHello("background");
|
||||
}
|
||||
});
|
||||
_background;
|
||||
chrome;
|
||||
function print(method, ...args) {
|
||||
return;
|
||||
@@ -389,6 +391,7 @@ describe('Output Directory Structure', () => {
|
||||
throw err;
|
||||
}
|
||||
})();
|
||||
_background;
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wxt",
|
||||
"type": "module",
|
||||
"version": "0.17.11",
|
||||
"version": "0.17.13-alpha1",
|
||||
"description": "Next gen framework for developing web extensions",
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
@@ -136,7 +136,7 @@
|
||||
"prompts": "^2.4.2",
|
||||
"publish-browser-extension": "^2.1.3",
|
||||
"unimport": "^3.4.0",
|
||||
"vite": "^5.1.3",
|
||||
"vite": "^5.2.8",
|
||||
"web-ext-run": "^0.2.0",
|
||||
"webextension-polyfill": "^0.10.0"
|
||||
},
|
||||
|
||||
Generated
+559
-219
File diff suppressed because it is too large
Load Diff
@@ -404,4 +404,62 @@ describe('Content Script UIs', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('mounted value', () => {
|
||||
describe('integrated', () => {
|
||||
it('should set the mounted value based on the onMounted return value', () => {
|
||||
const expected = Symbol();
|
||||
|
||||
const ui = createIntegratedUi(new ContentScriptContext('test'), {
|
||||
position: 'inline',
|
||||
onMount: () => expected,
|
||||
});
|
||||
expect(ui.mounted).toBeUndefined();
|
||||
|
||||
ui.mount();
|
||||
expect(ui.mounted).toBe(expected);
|
||||
|
||||
ui.remove();
|
||||
expect(ui.mounted).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('iframe', () => {
|
||||
it('should set the mounted value based on the onMounted return value', async () => {
|
||||
const expected = Symbol();
|
||||
|
||||
const ui = createIframeUi(new ContentScriptContext('test'), {
|
||||
page: '',
|
||||
position: 'inline',
|
||||
onMount: () => expected,
|
||||
});
|
||||
expect(ui.mounted).toBeUndefined();
|
||||
|
||||
ui.mount();
|
||||
expect(ui.mounted).toBe(expected);
|
||||
|
||||
ui.remove();
|
||||
expect(ui.mounted).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('shadow-root', () => {
|
||||
it('should set the mounted value based on the onMounted return value', async () => {
|
||||
const expected = Symbol();
|
||||
|
||||
const ui = await createShadowRootUi(new ContentScriptContext('test'), {
|
||||
name: 'test',
|
||||
position: 'inline',
|
||||
onMount: () => expected,
|
||||
});
|
||||
expect(ui.mounted).toBeUndefined();
|
||||
|
||||
ui.mount();
|
||||
expect(ui.mounted).toBe(expected);
|
||||
|
||||
ui.remove();
|
||||
expect(ui.mounted).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,12 +35,15 @@ export function createIntegratedUi<TMounted>(
|
||||
const remove = () => {
|
||||
options.onRemove?.(mounted);
|
||||
wrapper.remove();
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
|
||||
return {
|
||||
mounted,
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
wrapper,
|
||||
mount,
|
||||
remove,
|
||||
@@ -71,12 +74,15 @@ export function createIframeUi<TMounted>(
|
||||
const remove = () => {
|
||||
options.onRemove?.(mounted);
|
||||
wrapper.remove();
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
|
||||
return {
|
||||
mounted,
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
iframe,
|
||||
wrapper,
|
||||
mount,
|
||||
@@ -116,7 +122,7 @@ export async function createShadowRootUi<TMounted>(
|
||||
});
|
||||
shadowHost.setAttribute('data-wxt-shadow-root', '');
|
||||
|
||||
let mounted: TMounted;
|
||||
let mounted: TMounted | undefined;
|
||||
|
||||
const mount = () => {
|
||||
// Add shadow root element to DOM
|
||||
@@ -134,6 +140,8 @@ export async function createShadowRootUi<TMounted>(
|
||||
// Remove children from uiContainer
|
||||
while (uiContainer.lastChild)
|
||||
uiContainer.removeChild(uiContainer.lastChild);
|
||||
// Clear mounted value
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
@@ -144,7 +152,9 @@ export async function createShadowRootUi<TMounted>(
|
||||
uiContainer,
|
||||
mount,
|
||||
remove,
|
||||
mounted: mounted!,
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
WxtBuilder,
|
||||
WxtBuilderServer,
|
||||
WxtDevServer,
|
||||
WxtHooks,
|
||||
} from '~/types';
|
||||
import * as wxtPlugins from './plugins';
|
||||
import {
|
||||
@@ -16,9 +17,13 @@ import {
|
||||
VirtualEntrypointType,
|
||||
VirtualModuleId,
|
||||
} from '~/core/utils/virtual-modules';
|
||||
import { Hookable } from 'hookable';
|
||||
import { toArray } from '~/core/utils/arrays';
|
||||
import { safeVarName } from '~/core/utils/strings';
|
||||
|
||||
export async function createViteBuilder(
|
||||
wxtConfig: ResolvedConfig,
|
||||
hooks: Hookable<WxtHooks>,
|
||||
server?: WxtDevServer,
|
||||
): Promise<WxtBuilder> {
|
||||
const vite = await import('vite');
|
||||
@@ -83,14 +88,22 @@ export async function createViteBuilder(
|
||||
plugins.push(wxtPlugins.cssEntrypoints(entrypoint, wxtConfig));
|
||||
}
|
||||
|
||||
const iifeReturnValueName = safeVarName(entrypoint.name);
|
||||
const libMode: vite.UserConfig = {
|
||||
mode: wxtConfig.mode,
|
||||
plugins,
|
||||
esbuild: {
|
||||
// Add a footer with the returned value so it can return values to `scripting.executeScript`
|
||||
// Footer is added apart of esbuild to make sure it's not minified. It
|
||||
// get's removed if added to `build.rollupOptions.output.footer`
|
||||
// See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript#return_value
|
||||
footer: iifeReturnValueName + ';',
|
||||
},
|
||||
build: {
|
||||
lib: {
|
||||
entry,
|
||||
formats: ['iife'],
|
||||
name: '_',
|
||||
name: iifeReturnValueName,
|
||||
fileName: entrypoint.name,
|
||||
},
|
||||
rollupOptions: {
|
||||
@@ -198,6 +211,11 @@ export async function createViteBuilder(
|
||||
else entryConfig = getLibModeConfig(group);
|
||||
|
||||
const buildConfig = vite.mergeConfig(await getBaseConfig(), entryConfig);
|
||||
await hooks.callHook(
|
||||
'vite:build:extendConfig',
|
||||
toArray(group),
|
||||
buildConfig,
|
||||
);
|
||||
const result = await vite.build(buildConfig);
|
||||
return {
|
||||
entrypoints: group,
|
||||
@@ -214,9 +232,9 @@ export async function createViteBuilder(
|
||||
},
|
||||
};
|
||||
const baseConfig = await getBaseConfig();
|
||||
const viteServer = await vite.createServer(
|
||||
vite.mergeConfig(baseConfig, serverConfig),
|
||||
);
|
||||
const finalConfig = vite.mergeConfig(baseConfig, serverConfig);
|
||||
await hooks.callHook('vite:devServer:extendConfig', finalConfig);
|
||||
const viteServer = await vite.createServer(finalConfig);
|
||||
|
||||
const server: WxtBuilderServer = {
|
||||
async listen() {
|
||||
|
||||
@@ -5,9 +5,8 @@ import path from 'node:path';
|
||||
|
||||
let increment = 0;
|
||||
|
||||
export function bundleAnalysis(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
): vite.Plugin {
|
||||
export function bundleAnalysis(config: ResolvedConfig): vite.Plugin {
|
||||
// @ts-expect-error: Vite/Rollup type mismatch, but it's fine.
|
||||
return visualizer({
|
||||
template: 'raw-data',
|
||||
filename: path.resolve(
|
||||
|
||||
@@ -14,7 +14,7 @@ import { getEntrypointBundlePath } from '~/core/utils/entrypoints';
|
||||
*/
|
||||
export function cssEntrypoints(
|
||||
entrypoint: Entrypoint,
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
config: ResolvedConfig,
|
||||
): vite.Plugin {
|
||||
return {
|
||||
name: 'wxt:css-entrypoint',
|
||||
|
||||
@@ -12,7 +12,7 @@ let reactRefreshPreamble = '';
|
||||
* Pre-renders the HTML entrypoints when building the extension to connect to the dev server.
|
||||
*/
|
||||
export function devHtmlPrerender(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
config: ResolvedConfig,
|
||||
server: WxtDevServer | undefined,
|
||||
): vite.PluginOption {
|
||||
const htmlReloadId = '@wxt/reload-html';
|
||||
@@ -133,7 +133,7 @@ export function devHtmlPrerender(
|
||||
}
|
||||
|
||||
export function pointToDevServer(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
config: ResolvedConfig,
|
||||
server: WxtDevServer,
|
||||
id: string,
|
||||
document: Document,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ResolvedConfig, WxtDevServer } from '~/types';
|
||||
* Defines global constants about the dev server. Helps scripts connect to the server's web socket.
|
||||
*/
|
||||
export function devServerGlobals(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
config: ResolvedConfig,
|
||||
server: WxtDevServer | undefined,
|
||||
): Plugin {
|
||||
return {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { fetchCached } from '~/core/utils/network';
|
||||
* @example
|
||||
* import "url:https://google-tagmanager.com/gtag?id=XYZ";
|
||||
*/
|
||||
export function download(config: Omit<ResolvedConfig, 'builder'>): Plugin {
|
||||
export function download(config: ResolvedConfig): Plugin {
|
||||
return {
|
||||
name: 'wxt:download',
|
||||
resolveId(id) {
|
||||
|
||||
@@ -6,9 +6,7 @@ import type * as vite from 'vite';
|
||||
* `webextension-polyfill` module to a virtual module and exporting the `chrome` global from the
|
||||
* virtual module.
|
||||
*/
|
||||
export function excludeBrowserPolyfill(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
): vite.Plugin {
|
||||
export function excludeBrowserPolyfill(config: ResolvedConfig): vite.Plugin {
|
||||
const virtualId = 'virtual:wxt-webextension-polyfill-disabled';
|
||||
|
||||
return {
|
||||
|
||||
@@ -2,9 +2,7 @@ import type * as vite from 'vite';
|
||||
import { ResolvedConfig } from '~/types';
|
||||
import { getGlobals } from '~/core/utils/globals';
|
||||
|
||||
export function globals(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
): vite.PluginOption {
|
||||
export function globals(config: ResolvedConfig): vite.PluginOption {
|
||||
return {
|
||||
name: 'wxt:globals',
|
||||
config() {
|
||||
|
||||
@@ -20,7 +20,7 @@ import { normalizePath } from '~/core/utils/paths';
|
||||
*/
|
||||
export function multipageMove(
|
||||
entrypoints: Entrypoint[],
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
config: ResolvedConfig,
|
||||
): vite.Plugin {
|
||||
return {
|
||||
name: 'wxt:multipage-move',
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { ResolvedConfig } from '~/types';
|
||||
import type * as vite from 'vite';
|
||||
|
||||
export function tsconfigPaths(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
): vite.Plugin {
|
||||
export function tsconfigPaths(config: ResolvedConfig): vite.Plugin {
|
||||
return {
|
||||
name: 'wxt:aliases',
|
||||
async config() {
|
||||
|
||||
@@ -15,9 +15,7 @@ const ENABLED_EXTENSIONS = new Set([
|
||||
/**
|
||||
* Inject any global imports defined by unimport
|
||||
*/
|
||||
export function unimport(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
): vite.PluginOption {
|
||||
export function unimport(config: ResolvedConfig): vite.PluginOption {
|
||||
const options = config.imports;
|
||||
if (options === false) return [];
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import { ResolvedConfig } from '~/types';
|
||||
* `npm list` and inline them automatically.
|
||||
*/
|
||||
export function webextensionPolyfillMock(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
config: ResolvedConfig,
|
||||
): vite.PluginOption {
|
||||
return {
|
||||
name: 'wxt:testing-inline-deps',
|
||||
|
||||
@@ -223,6 +223,7 @@ function resolveZipConfig(
|
||||
artifactTemplate: '{{name}}-{{version}}-{{browser}}.zip',
|
||||
sourcesRoot: root,
|
||||
includeSources: [],
|
||||
compressionLevel: 9,
|
||||
...mergedConfig.zip,
|
||||
excludeSources: [
|
||||
'**/node_modules',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ResolvedConfig } from '~/types';
|
||||
|
||||
export function getGlobals(
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
config: ResolvedConfig,
|
||||
): Array<{ name: string; value: any; type: string }> {
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ export async function isOnline(): Promise<boolean> {
|
||||
*/
|
||||
export async function fetchCached(
|
||||
url: string,
|
||||
config: Omit<ResolvedConfig, 'builder'>,
|
||||
config: ResolvedConfig,
|
||||
): Promise<string> {
|
||||
let content: string = '';
|
||||
|
||||
|
||||
@@ -5,6 +5,14 @@ export function kebabCaseAlphanumeric(str: string): string {
|
||||
.replace(/\s+/g, '-'); // Replace spaces with hyphens
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a safe variable name for a given string.
|
||||
*/
|
||||
export function safeVarName(str: string): string {
|
||||
// _ prefix to ensure it doesn't start with a number
|
||||
return '_' + kebabCaseAlphanumeric(str).replace('-', '_');
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes import statements from the top of a file. Keeps import.meta and inline, async `import()`
|
||||
* calls.
|
||||
|
||||
@@ -288,6 +288,7 @@ export const fakeResolvedConfig = fakeObjectCreator<ResolvedConfig>(() => {
|
||||
name: faker.person.firstName().toLowerCase(),
|
||||
downloadedPackagesDir: fakeDir(),
|
||||
downloadPackages: [],
|
||||
compressionLevel: 9,
|
||||
},
|
||||
transformManifest: () => {},
|
||||
userConfigMetadata: {},
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ export async function registerWxt(
|
||||
const hooks = createHooks<WxtHooks>();
|
||||
const config = await resolveConfig(inlineConfig, command);
|
||||
const server = await getServer?.(config);
|
||||
const builder = await createViteBuilder(config, server);
|
||||
const builder = await createViteBuilder(config, hooks, server);
|
||||
const pm = await createWxtPackageManager(config.root);
|
||||
|
||||
wxt = {
|
||||
|
||||
+9
-1
@@ -135,7 +135,15 @@ async function zipDir(
|
||||
}
|
||||
}
|
||||
await options?.additionalWork?.(archive);
|
||||
const buffer = await archive.generateAsync({ type: 'base64' });
|
||||
const buffer = await archive.generateAsync({
|
||||
type: 'base64',
|
||||
...(wxt.config.zip.compressionLevel === 0
|
||||
? { compression: 'STORE' }
|
||||
: {
|
||||
compression: 'DEFLATE',
|
||||
compressionOptions: { level: wxt.config.zip.compressionLevel },
|
||||
}),
|
||||
});
|
||||
await fs.writeFile(outputPath, buffer, 'base64');
|
||||
}
|
||||
|
||||
|
||||
+48
-5
@@ -202,6 +202,14 @@ export interface InlineConfig {
|
||||
* ["@scope/package-name@1.1.3", "package-name@^2"]
|
||||
*/
|
||||
downloadPackages?: string[];
|
||||
/**
|
||||
* Compression level to use when zipping files.
|
||||
*
|
||||
* Levels: 0 (no compression) to 9 (maximum compression).
|
||||
*
|
||||
* @default 9
|
||||
*/
|
||||
compressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -361,6 +369,28 @@ export type WxtViteConfig = Omit<
|
||||
'root' | 'configFile' | 'mode'
|
||||
>;
|
||||
|
||||
// TODO: Move into @wxt/vite-builder
|
||||
export interface WxtHooks {
|
||||
/**
|
||||
* Called when WXT has created Vite's config for a build step. Useful if you
|
||||
* want to add plugins or update the vite config per entrypoint group.
|
||||
*
|
||||
* @param entrypoints The list of entrypoints being built with the provided config.
|
||||
* @param viteConfig The config that will be used for the dev server.
|
||||
*/
|
||||
'vite:build:extendConfig': (
|
||||
entrypoints: readonly Entrypoint[],
|
||||
viteConfig: vite.InlineConfig,
|
||||
) => HookResult;
|
||||
/**
|
||||
* Called when WXT has created Vite's config for the dev server. Useful if
|
||||
* you want to add plugins or update the vite config per entrypoint group.
|
||||
*
|
||||
* @param viteConfig The config that will be used to build the entrypoints. Can be updated by reference.
|
||||
*/
|
||||
'vite:devServer:extendConfig': (config: vite.InlineConfig) => HookResult;
|
||||
}
|
||||
|
||||
export interface BuildOutput {
|
||||
manifest: Manifest.WebExtensionManifest;
|
||||
publicAssets: OutputAsset[];
|
||||
@@ -564,8 +594,8 @@ export interface BaseContentScriptEntrypointOptions
|
||||
* - `"manifest"`: The content script will be added to the `content_scripts` entry in the
|
||||
* manifest. This is the normal and most well known way of registering a content script.
|
||||
* - `"runtime"`: The content script's `matches` is added to `host_permissions` and you are
|
||||
* responsible for using the scripting API to register the content script dynamically at
|
||||
* runtime.
|
||||
* responsible for using the scripting API to register/execute the content script
|
||||
* dynamically at runtime.
|
||||
*
|
||||
* @default "manifest"
|
||||
*/
|
||||
@@ -707,16 +737,24 @@ export interface IsolatedWorldContentScriptDefinition
|
||||
extends IsolatedWorldContentScriptEntrypointOptions {
|
||||
/**
|
||||
* Main function executed when the content script is loaded.
|
||||
*
|
||||
* When running a content script with `browser.scripting.executeScript`,
|
||||
* values returned from this function will be returned in the `executeScript`
|
||||
* result as well. Otherwise returning a value does nothing.
|
||||
*/
|
||||
main(ctx: ContentScriptContext): void | Promise<void>;
|
||||
main(ctx: ContentScriptContext): any | Promise<any>;
|
||||
}
|
||||
|
||||
export interface MainWorldContentScriptDefinition
|
||||
extends MainWorldContentScriptEntrypointOptions {
|
||||
/**
|
||||
* Main function executed when the content script is loaded.
|
||||
*
|
||||
* When running a content script with `browser.scripting.executeScript`,
|
||||
* values returned from this function will be returned in the `executeScript`
|
||||
* result as well. Otherwise returning a value does nothing.
|
||||
*/
|
||||
main(): void | Promise<void>;
|
||||
main(): any | Promise<any>;
|
||||
}
|
||||
|
||||
export type ContentScriptDefinition =
|
||||
@@ -733,8 +771,12 @@ export interface BackgroundDefinition extends BackgroundEntrypointOptions {
|
||||
export interface UnlistedScriptDefinition extends BaseEntrypointOptions {
|
||||
/**
|
||||
* Main function executed when the unlisted script is ran.
|
||||
*
|
||||
* When running a content script with `browser.scripting.executeScript`,
|
||||
* values returned from this function will be returned in the `executeScript`
|
||||
* result as well. Otherwise returning a value does nothing.
|
||||
*/
|
||||
main(): void | Promise<void>;
|
||||
main(): any | Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1057,6 +1099,7 @@ export interface ResolvedConfig {
|
||||
sourcesRoot: string;
|
||||
downloadedPackagesDir: string;
|
||||
downloadPackages: string[];
|
||||
compressionLevel: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
||||
};
|
||||
/**
|
||||
* @deprecated Use `build:manifestGenerated` hook instead.
|
||||
|
||||
@@ -2,16 +2,23 @@ import definition from 'virtual:user-content-script-isolated-world-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { ContentScriptContext } from 'wxt/client';
|
||||
|
||||
(async () => {
|
||||
const result = (async () => {
|
||||
try {
|
||||
const { main, ...options } = definition;
|
||||
const ctx = new ContentScriptContext(import.meta.env.ENTRYPOINT, options);
|
||||
|
||||
await main(ctx);
|
||||
return await main(ctx);
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
`The content script "${import.meta.env.ENTRYPOINT}" crashed on startup!`,
|
||||
err,
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
})();
|
||||
|
||||
// Return the main function's result to the background when executed via the
|
||||
// scripting API. Default export causes the IIFE to return a value.
|
||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript#return_value
|
||||
// Tested on both Chrome and Firefox
|
||||
export default result;
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import definition from 'virtual:user-content-script-main-world-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
|
||||
(async () => {
|
||||
const result = (async () => {
|
||||
try {
|
||||
const { main } = definition;
|
||||
await main();
|
||||
return await main();
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
`The content script "${import.meta.env.ENTRYPOINT}" crashed on startup!`,
|
||||
err,
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
})();
|
||||
|
||||
// Return the main function's result to the background when executed via the
|
||||
// scripting API. Default export causes the IIFE to return a value.
|
||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript#return_value
|
||||
// Tested on both Chrome and Firefox
|
||||
export default result;
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
import definition from 'virtual:user-unlisted-script-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
|
||||
(async () => {
|
||||
const result = (async () => {
|
||||
try {
|
||||
await definition.main();
|
||||
return await definition.main();
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
`The unlisted script "${import.meta.env.ENTRYPOINT}" crashed on startup!`,
|
||||
err,
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
})();
|
||||
|
||||
// Return the main function's result to the background when executed via the
|
||||
// scripting API. Default export causes the IIFE to return a value.
|
||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript#return_value
|
||||
// Tested on both Chrome and Firefox
|
||||
export default result;
|
||||
|
||||
@@ -10,5 +10,9 @@ export default defineConfig({
|
||||
},
|
||||
vite: () => ({
|
||||
plugins: [vue()],
|
||||
build: {
|
||||
// Enabling sourcemaps with Vue during development is known to cause problems with Vue
|
||||
sourcemap: false,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user