Compare commits

..

25 Commits

Author SHA1 Message Date
Aaron 55444858bc ci: Add new modules as release targets 2024-06-13 23:44:28 -05:00
Aaron 771ea03069 feat: Add @wxt-dev/module-solid package (#730) 2024-06-13 23:23:32 -05:00
Aaron 38b71d1350 chore: Remove extra dependencies 2024-06-13 23:08:17 -05:00
Aaron cb781aceb5 chore: Remove extra dependencies 2024-06-13 23:05:48 -05:00
Aaron d53c792218 chore: Remove dependencies from vue module 2024-06-13 23:03:16 -05:00
Aaron 907f4d3672 feat: Add @wxt-dev/module-react package (#729) 2024-06-13 22:53:40 -05:00
Aaron 8432d73a6b fix: Generalize react-refresh preamble logic to virtualize all inline scripts (#728) 2024-06-13 19:17:23 -05:00
Aaron 94a5435089 docs: Add missing vue install step 2024-06-13 16:39:09 -05:00
Aaron edf3cf3f17 feat: Add @wxt-dev/module-vue package (#726) 2024-06-13 16:36:37 -05:00
Aaron 48783baec3 chore(deps): Upgrade and sync all dependencies (#725) 2024-06-13 15:44:00 -05:00
Aaron c70f047696 chore: Add taze to project (#724) 2024-06-13 15:17:21 -05:00
Aaron e6e0c713bc feat: Add @wxt-dev/module-vue package (#716) 2024-06-13 15:16:45 -05:00
Aaron 3691554a73 docs: Update contributor docs with release steps 2024-06-13 14:58:57 -05:00
Aaron 1a3436606b fix(dev): Fix CSP error loading HTML plugins (#723) 2024-06-13 14:49:50 -05:00
GitHub Actions 2c9e7750ec chore(release): wxt v0.18.6 2024-06-13 17:28:34 +00:00
Aaron fa67910007 fix(modules): Add modules to TS project so type augmentation works (#722) 2024-06-13 12:25:18 -05:00
Aaron c77773eb20 feat(modules): Add new addImportPreset helper function (#720) 2024-06-13 12:20:09 -05:00
Aaron 148f3d53a6 fix(modules): Re-export WxtModule type from wxt/modules to prevent TS2742 (#721) 2024-06-13 12:19:15 -05:00
Aaron c7af789173 fix(types): Module options param is optional, but types did not reflect that (#719) 2024-06-13 11:20:59 -05:00
Aaron 274d39b9a4 chore(dev-deps): Upgrade typescript to 5.4 (#718) 2024-06-13 00:38:11 -05:00
Aaron d1edb2da0e chore: Cache workspace dependency builds (#715) 2024-06-12 22:34:08 -05:00
Aaron ed860027ef ci: Fix sync-releases script 2024-06-12 00:51:11 -05:00
Aaron 488fa6e773 ci: Fix sync-releases workflow 2024-06-12 00:48:40 -05:00
Aaron ea51cc04a9 Fix changelog 2024-06-12 00:46:23 -05:00
Aaron 6d1761533f ci: Fix compare url generation 2024-06-12 00:45:39 -05:00
46 changed files with 3046 additions and 1000 deletions
+4
View File
@@ -8,6 +8,10 @@ on:
type: choice
options:
- wxt
- module-react
- module-vue
- module-svelte
- module-solid
jobs:
validate:
+5 -5
View File
@@ -8,17 +8,17 @@ on:
type: choice
options:
- wxt
- module-react
- module-vue
- module-svelte
- module-solid
jobs:
sync:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 18
cache: pnpm
- uses: ./.github/actions/setup
- run: pnpm tsx scripts/sync-releases.ts ${{ inputs.package }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+6
View File
@@ -13,6 +13,12 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm check
builds:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm -r --sequential build
build-demo:
runs-on: ubuntu-22.04
steps:
+1
View File
@@ -20,3 +20,4 @@ templates/*/package-lock.json
docs/api/reference
stats.html
.tool-versions
.cache
+17
View File
@@ -112,3 +112,20 @@ cp -r templates/vanilla templates/<new-template-name>
```
That's it. Once your template is merged, it will be available inside `wxt init` immediately. You don't need to release a new version of WXT to release a new template.
## Releasing Updates
Releases are done with GitHub actions:
- Use the [Release workflow](https://github.com/wxt-dev/wxt/actions/workflows/release.yml) to release a single package in the monorepo. This automatically detects the version change with conventional commits, builds and uploads the package to NPM, and creates a GitHub release.
- Use the [Sync Releases workflow](https://github.com/wxt-dev/wxt/actions/workflows/sync-releases.yml) to sync the GitHub releases with changes to the changelog. To change a release, update the `CHANGELOG.md` file and run the workflow. It will sync the releases of a single package in the monorepo.
## Upgrading Dependencies
Use [`taze`](https://www.npmjs.com/package/taze) to upgrade dependencies throughout the entire monorepo.
```ts
pnpm dlx taze -r
```
Configuration is in [`taze.config.ts`](./taze.config.ts).
+22 -17
View File
@@ -5,9 +5,9 @@
"node": ">=18.20.3",
"pnpm": "^8.6.3"
},
"packageManager": "pnpm@8.6.3",
"packageManager": "pnpm@8.15.8",
"scripts": {
"check": "check && pnpm -r run check",
"check": "check && pnpm -r --sequential run check",
"test": "vitest",
"test:coverage": "vitest run --coverage.enabled \"--coverage.include=packages/wxt/src/**\" \"--coverage.exclude=packages/wxt/src/core/utils/testing/**\" \"--coverage.exclude=**/*.d.ts\" \"--coverage.exclude=**/fixtures/**\"",
"prepare": "simple-git-hooks",
@@ -15,31 +15,36 @@
"docs:gen": "typedoc --options docs/typedoc.json",
"docs:dev": "pnpm -s docs:gen && vitepress dev docs",
"docs:build": "pnpm -s docs:gen && vitepress build docs",
"docs:preview": "pnpm -s docs:gen && vitepress preview docs"
"docs:preview": "pnpm -s docs:gen && vitepress preview docs",
"build-deps": "pnpm tsx scripts/build-deps.ts"
},
"devDependencies": {
"@aklinker1/check": "^1.1.1",
"@aklinker1/check": "^1.3.1",
"@types/fs-extra": "^11.0.4",
"@vitest/coverage-v8": "^1.0.1",
"@vitest/coverage-v8": "^1.6.0",
"changelogen": "^0.5.5",
"consola": "^3.2.3",
"execa": "^9.1.0",
"fs-extra": "^11.1.1",
"lint-staged": "^15.2.0",
"dependency-graph": "^1.0.0",
"execa": "^9.2.0",
"fast-glob": "^3.3.2",
"fs-extra": "^11.2.0",
"hasha": "^6.0.0",
"lint-staged": "^15.2.7",
"npm-run-all": "^4.1.5",
"prettier": "^3.3.0",
"simple-git-hooks": "^2.9.0",
"tsx": "^4.11.2",
"prettier": "^3.3.2",
"simple-git-hooks": "^2.11.1",
"tsx": "^4.15.4",
"typedoc": "^0.25.4",
"typedoc-plugin-markdown": "4.0.0-next.23",
"typedoc-vitepress-theme": "1.0.0-next.3",
"typescript": "^5.3.2",
"vitepress": "^1.2.2",
"vitest": "^1.5.3",
"typescript": "^5.4.5",
"vitepress": "^1.2.3",
"vitest": "^1.6.0",
"vitest-mock-extended": "^1.3.1",
"vitest-plugin-random-seed": "^1.0.2",
"vue": "^3.3.10",
"wxt": "workspace:*"
"vitest-plugin-random-seed": "^1.1.0",
"vue": "^3.4.27",
"wxt": "workspace:*",
"yaml": "^2.4.5"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
+32
View File
@@ -0,0 +1,32 @@
# `@wxt-dev/module-react`
Enables the use of [React](https://react.dev/) in your web extension, in HTML pages and content scripts.
This plugin makes a few changes:
1. Adds `@vitejs/plugin-react` to vite
2. Adds the [`react` preset](https://github.com/unjs/unimport/blob/main/src/presets/react.ts) to auto-imports
## Usage
```sh
pnpm i react react-dom
pnpm i -D @wxt-dev/module-react
```
Then add the module to your config:
```ts
// wxt.config.ts
export default defineConfig({
// Required
modules: ['@wxt-dev/module-react'],
// Optional: Pass options to the module:
react: {
vite: {
// ...
},
},
});
```
+41
View File
@@ -0,0 +1,41 @@
{
"name": "@wxt-dev/module-react",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"files": [
"dist"
],
"scripts": {
"build": "pnpm -s build-deps && unbuild",
"check": "pnpm -s build-deps && check",
"build-deps": "pnpm -ws build-deps @wxt-dev/module-react"
},
"peerDependencies": {
"wxt": ">=0.18.5"
},
"dependencies": {
"@vitejs/plugin-react": "^4.3.1"
},
"devDependencies": {
"@aklinker1/check": "^1.3.1",
"publint": "^0.2.8",
"typescript": "^5.4.5",
"unbuild": "^2.0.0",
"wxt": "workspace:*"
}
}
+27
View File
@@ -0,0 +1,27 @@
import 'wxt';
import { addImportPreset, addViteConfig, defineWxtModule } from 'wxt/modules';
import react, { Options as PluginOptions } from '@vitejs/plugin-react';
export default defineWxtModule<ReactModuleOptions>({
name: '@wxt-dev/module-react',
configKey: 'react',
setup(wxt, options) {
const { vite } = options ?? {};
addViteConfig(wxt, () => ({
plugins: [react(vite)],
}));
addImportPreset(wxt, 'react');
},
});
export interface ReactModuleOptions {
vite?: PluginOptions;
}
declare module 'wxt' {
export interface InlineConfig {
react?: ReactModuleOptions;
}
}
+4
View File
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"exclude": ["node_modules/**", "dist/**"]
}
+32
View File
@@ -0,0 +1,32 @@
# `@wxt-dev/module-solid`
Enables the use of [SolidJS](https://www.solidjs.com/) in your web extension, in HTML pages and content scripts.
This plugin makes a few changes:
1. Adds `vite-plugin-solid` to vite
2. Adds the [`solid-js` preset](https://github.com/unjs/unimport/blob/main/src/presets/solid.ts) to auto-imports
## Usage
```sh
pnpm i solid-js
pnpm i -D @wxt-dev/module-solid
```
Then add the module to your config:
```ts
// wxt.config.ts
export default defineConfig({
// Required
modules: ['@wxt-dev/module-solid'],
// Optional: Pass options to the module:
solid: {
vite: {
// ...
},
},
});
```
+41
View File
@@ -0,0 +1,41 @@
{
"name": "@wxt-dev/module-solid",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"files": [
"dist"
],
"scripts": {
"build": "pnpm -s build-deps && unbuild",
"check": "pnpm -s build-deps && check",
"build-deps": "pnpm -ws build-deps @wxt-dev/module-solid"
},
"peerDependencies": {
"wxt": ">=0.18.5"
},
"dependencies": {
"vite-plugin-solid": "^2.10.2"
},
"devDependencies": {
"@aklinker1/check": "^1.3.1",
"publint": "^0.2.8",
"typescript": "^5.4.5",
"unbuild": "^2.0.0",
"wxt": "workspace:*"
}
}
+27
View File
@@ -0,0 +1,27 @@
import 'wxt';
import { addImportPreset, addViteConfig, defineWxtModule } from 'wxt/modules';
import solid, { Options as PluginOptions } from 'vite-plugin-solid';
export default defineWxtModule<SolidModuleOptions>({
name: '@wxt-dev/module-solid',
configKey: 'solid',
setup(wxt, options) {
const { vite } = options ?? {};
addViteConfig(wxt, () => ({
plugins: [solid(vite)],
}));
addImportPreset(wxt, 'solid-js');
},
});
export interface SolidModuleOptions {
vite?: PluginOptions;
}
declare module 'wxt' {
export interface InlineConfig {
solid?: SolidModuleOptions;
}
}
+4
View File
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"exclude": ["node_modules/**", "dist/**"]
}
+32
View File
@@ -0,0 +1,32 @@
# `@wxt-dev/module-svelte`
Enables the use of [Svelte](https://svelte.dev/) in your web extension, in HTML pages and content scripts.
This plugin makes a few changes:
1. Adds `@sveltejs/vite-plugin-svelte` to vite
2. Adds the [`svelte` preset](https://github.com/unjs/unimport/blob/main/src/presets/vue.ts) to auto-imports
## Usage
```sh
pnpm i svelte
pnpm i -D @wxt-dev/module-svelte
```
Then add the module to your config:
```ts
// wxt.config.ts
export default defineConfig({
// Required
modules: ['@wxt-dev/module-svelte'],
// Optional: Pass options to the module:
svelte: {
vite: {
// ...
},
},
});
```
+41
View File
@@ -0,0 +1,41 @@
{
"name": "@wxt-dev/module-svelte",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"files": [
"dist"
],
"scripts": {
"build": "pnpm -s build-deps && unbuild",
"check": "pnpm -s build-deps && check",
"build-deps": "pnpm -ws build-deps @wxt-dev/module-svelte"
},
"peerDependencies": {
"wxt": ">=0.18.5"
},
"dependencies": {
"@sveltejs/vite-plugin-svelte": "^3.1.1"
},
"devDependencies": {
"@aklinker1/check": "^1.3.1",
"publint": "^0.2.8",
"typescript": "^5.4.5",
"unbuild": "^2.0.0",
"wxt": "workspace:*"
}
}
+38
View File
@@ -0,0 +1,38 @@
import 'wxt';
import { addImportPreset, addViteConfig, defineWxtModule } from 'wxt/modules';
import {
svelte,
vitePreprocess,
Options as PluginOptions,
} from '@sveltejs/vite-plugin-svelte';
export default defineWxtModule<SvelteModuleOptions>({
name: '@wxt-dev/module-svelte',
configKey: 'svelte',
setup(wxt, options) {
const { vite } = options ?? {};
addViteConfig(wxt, () => ({
plugins: [
svelte({
// Using a svelte.config.js file causes a segmentation fault when importing the file
configFile: false,
preprocess: [vitePreprocess()],
...vite,
}),
],
}));
addImportPreset(wxt, 'svelte');
},
});
export interface SvelteModuleOptions {
vite?: Partial<PluginOptions>;
}
declare module 'wxt' {
export interface InlineConfig {
svelte?: SvelteModuleOptions;
}
}
+4
View File
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"exclude": ["node_modules/**", "dist/**"]
}
+36
View File
@@ -0,0 +1,36 @@
# `@wxt-dev/module-vue`
Enables the use of [Vue](https://vuejs.org/) in your web extension, in HTML pages and content scripts.
This plugin makes a few changes:
1. Adds `@vitejs/plugin-vue` to vite config
2. Adds the [`vue` preset](https://github.com/unjs/unimport/blob/main/src/presets/vue.ts) to auto-imports
3. Applies sourcemap fix to prevent HMR errors during development
4. Enable auto-imports in `.vue` files
## Usage
```sh
pnpm i vue
pnpm i -D @wxt-dev/module-vue
```
Then add the module to your config:
```ts
// wxt.config.ts
export default defineConfig({
// Required
modules: ['@wxt-dev/module-vue'],
// Optional: Pass options to the module:
vue: {
vite: {
script: {
propsDestructure: true,
},
},
},
});
```
+41
View File
@@ -0,0 +1,41 @@
{
"name": "@wxt-dev/module-vue",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"files": [
"dist"
],
"scripts": {
"build": "pnpm -s build-deps && unbuild",
"check": "pnpm -s build-deps && check",
"build-deps": "pnpm -ws build-deps @wxt-dev/module-vue"
},
"peerDependencies": {
"wxt": ">=0.18.5"
},
"dependencies": {
"@vitejs/plugin-vue": "^5.0.5"
},
"devDependencies": {
"@aklinker1/check": "^1.3.1",
"publint": "^0.2.8",
"typescript": "^5.4.5",
"unbuild": "^2.0.0",
"wxt": "workspace:*"
}
}
+47
View File
@@ -0,0 +1,47 @@
import 'wxt';
import { addImportPreset, addViteConfig, defineWxtModule } from 'wxt/modules';
import vue, { Options as ViteOptions } from '@vitejs/plugin-vue';
export default defineWxtModule<VueModuleOptions>({
name: '@wxt-dev/module-vue',
configKey: 'vue',
setup(wxt, options) {
const { vite } = options ?? {};
// Add plugin & set sourcemap option
addViteConfig(wxt, ({ command }) => ({
// @ts-ignore: Ignore vite version issues
plugins: [vue(vite)],
build: {
// Fixes known issue: https://github.com/wxt-dev/wxt/pull/607
sourcemap: false,
},
}));
// Enable auto-imports in template files
wxt.hooks.hook('ready', (wxt) => {
if (!wxt.config.imports) return;
wxt.config.imports.addons ??= {};
if (!Array.isArray(wxt.config.imports.addons)) {
wxt.config.imports.addons.vueTemplate = true;
} else {
wxt.logger.warn(
'Could not enable auto-imports in vue templates when using and array for imports.addons',
);
}
});
addImportPreset(wxt, 'vue');
},
});
export interface VueModuleOptions {
vite?: ViteOptions;
}
declare module 'wxt' {
export interface InlineConfig {
vue?: VueModuleOptions;
}
}
+4
View File
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"exclude": ["node_modules/**", "dist/**"]
}
+14 -14
View File
@@ -4,28 +4,28 @@
"private": true,
"type": "module",
"scripts": {
"dev": "pnpm build:deps && wxt",
"build:deps": "pnpm --filter wxt build",
"build": "pnpm build:deps && wxt build",
"build:all": "pnpm build:deps && run-s -s 'build:all:*'",
"dev": "pnpm -s build-deps && wxt",
"build": "pnpm -s build-deps && wxt build",
"build:all": "pnpm -s build-deps && run-s -s 'build:all:*'",
"build:all:chrome-mv3": "wxt build",
"build:all:chrome-mv2": "wxt build --mv2",
"build:all:firefox-mv3": "wxt build -b firefox --mv3",
"build:all:firefox-mv2": "wxt build -b firefox",
"test": "pnpm build:deps && vitest",
"zip": "pnpm build:deps && wxt zip",
"check": "pnpm build:deps && check",
"postinstall": "pnpm build:deps && wxt prepare"
"test": "pnpm -s build-deps && vitest",
"zip": "pnpm -s build-deps && wxt zip",
"check": "pnpm -s build-deps && check",
"postinstall": "pnpm -s build-deps && wxt prepare",
"build-deps": "pnpm -sw build-deps wxt-demo"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^18.2.34",
"@types/react-dom": "^18.2.14",
"sass": "^1.69.5",
"typescript": "^5.3.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"sass": "^1.77.5",
"typescript": "^5.4.5",
"wxt": "workspace:*"
}
}
-1
View File
@@ -6,6 +6,5 @@ export default defineProject({
mockReset: true,
restoreMocks: true,
},
// @ts-expect-error
plugins: [WxtVitest()],
});
+19 -1
View File
@@ -1,8 +1,26 @@
# Changelog
## v0.18.6
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.5...wxt-v0.18.6)
### 🚀 Enhancements
- **modules:** Add new `addImportPreset` helper function ([#720](https://github.com/wxt-dev/wxt/pull/720))
### 🩹 Fixes
- **types:** Module `options` param is optional, but types did not reflect that ([#719](https://github.com/wxt-dev/wxt/pull/719))
- **modules:** Re-export `WxtModule` type from `wxt/modules` to prevent TS2742 ([#721](https://github.com/wxt-dev/wxt/pull/721))
- **modules:** Add modules to TS project so type augmentation works ([#722](https://github.com/wxt-dev/wxt/pull/722))
### 🏡 Chore
- **dev-deps:** Upgrade typescript to 5.4 ([#718](https://github.com/wxt-dev/wxt/pull/718))
## v0.18.5
[compare changes](https://github.com/wxt-dev/wxt/compare/0.18.4...0.18.5)
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.4...wxt-v0.18.5)
### 🚀 Enhancements
@@ -280,8 +280,7 @@ describe('Output Directory Structure', () => {
----------------------------------------
import { l as logHello, i as initPlugins } from "./chunks/_virtual_wxt-plugins-OjKtWpmY.js";
function defineBackground(arg) {
if (typeof arg === "function")
return { main: arg };
if (typeof arg === "function") return { main: arg };
return arg;
}
const definition = defineBackground({
@@ -363,8 +362,7 @@ describe('Output Directory Structure', () => {
var _background = function() {
"use strict";
function defineBackground(arg) {
if (typeof arg === "function")
return { main: arg };
if (typeof arg === "function") return { main: arg };
return arg;
}
function logHello(name) {
@@ -375,4 +375,9 @@ describe('TypeScript Project', () => {
}"
`);
});
// TODO: Once a module has been published, use it here for testing - local files are never added to the .wxt/wxt.d.ts file
it.todo(
'should add modules from NPM to the TS project if they have a configKey',
);
});
+30 -29
View File
@@ -1,7 +1,7 @@
{
"name": "wxt",
"type": "module",
"version": "0.18.5",
"version": "0.18.6",
"description": "Next gen framework for developing web extensions",
"repository": {
"type": "git",
@@ -102,61 +102,62 @@
},
"dependencies": {
"@aklinker1/rollup-plugin-visualizer": "5.12.0",
"@types/webextension-polyfill": "^0.10.5",
"@types/webextension-polyfill": "^0.10.7",
"@webext-core/fake-browser": "^1.3.1",
"@webext-core/isolated-element": "^1.1.2",
"@webext-core/match-patterns": "^1.0.3",
"async-mutex": "^0.4.0",
"c12": "^1.5.1",
"async-mutex": "^0.4.1",
"c12": "^1.11.1",
"cac": "^6.7.14",
"chokidar": "^3.5.3",
"chokidar": "^3.6.0",
"ci-info": "^4.0.0",
"defu": "^6.1.3",
"defu": "^6.1.4",
"dequal": "^2.0.3",
"esbuild": "^0.19.5",
"fast-glob": "^3.3.1",
"filesize": "^10.0.8",
"fs-extra": "^11.1.1",
"get-port": "^7.0.0",
"giget": "^1.1.3",
"esbuild": "^0.19.12",
"fast-glob": "^3.3.2",
"filesize": "^10.1.2",
"fs-extra": "^11.2.0",
"get-port": "^7.1.0",
"giget": "^1.2.3",
"hookable": "^5.5.3",
"is-wsl": "^3.0.0",
"jiti": "^1.21.0",
"is-wsl": "^3.1.0",
"jiti": "^1.21.6",
"json5": "^2.2.3",
"jszip": "^3.10.1",
"linkedom": "^0.18.2",
"linkedom": "^0.18.3",
"magicast": "^0.3.4",
"minimatch": "^9.0.3",
"minimatch": "^9.0.4",
"natural-compare": "^1.4.0",
"normalize-path": "^3.0.0",
"nypm": "^0.3.8",
"ohash": "^1.1.3",
"open": "^10.1.0",
"ora": "^7.0.1",
"picocolors": "^1.0.0",
"picocolors": "^1.0.1",
"prompts": "^2.4.2",
"publish-browser-extension": "^2.1.3",
"unimport": "^3.4.0",
"vite": "^5.2.8",
"unimport": "^3.7.2",
"vite": "^5.3.0",
"web-ext-run": "^0.2.0",
"webextension-polyfill": "^0.10.0"
},
"devDependencies": {
"@aklinker1/check": "^1.1.1",
"@faker-js/faker": "^8.3.1",
"@aklinker1/check": "^1.3.1",
"@faker-js/faker": "^8.4.1",
"@types/fs-extra": "^11.0.4",
"@types/lodash.merge": "^4.6.9",
"@types/natural-compare": "^1.4.3",
"@types/node": "^20.10.3",
"@types/node": "^20.14.2",
"@types/normalize-path": "^3.0.2",
"@types/prompts": "^2.4.9",
"execa": "^9.1.0",
"execa": "^9.2.0",
"extract-zip": "^2.0.1",
"happy-dom": "^13.3.8",
"happy-dom": "^13.10.1",
"lodash.merge": "^4.6.2",
"p-map": "^7.0.0",
"publint": "^0.2.6",
"tsup": "^8.0.1",
"tsx": "^4.11.2",
"typescript": "^5.3.2"
"p-map": "^7.0.2",
"publint": "^0.2.8",
"tsup": "^8.1.0",
"tsx": "^4.15.4",
"typescript": "^5.4.5"
}
}
+47 -1
View File
@@ -1,5 +1,5 @@
import { fakeWxt } from '~/core/utils/testing/fake-objects';
import { addViteConfig } from '../modules';
import { addImportPreset, addViteConfig } from '../modules';
import { describe, it, expect } from 'vitest';
import { createHooks } from 'hookable';
@@ -37,4 +37,50 @@ describe('Module Utilities', () => {
expect(actual).toEqual(expected);
});
});
describe('addImportPreset', () => {
it('should add the import to the config', async () => {
const preset = 'vue';
const wxt = fakeWxt({ hooks: createHooks() });
addImportPreset(wxt, preset);
await wxt.hooks.callHook('ready', wxt);
expect(wxt.config.imports && wxt.config.imports.presets).toContain(
preset,
);
});
it('should not add duplicate presets', async () => {
const preset = 'vue';
const wxt = fakeWxt({
hooks: createHooks(),
config: {
imports: {
presets: ['vue', 'react'],
},
},
});
addImportPreset(wxt, preset);
await wxt.hooks.callHook('ready', wxt);
expect(wxt.config.imports && wxt.config.imports.presets).toHaveLength(2);
});
it("should not enable imports if they've been disabled", async () => {
const preset = 'vue';
const wxt = fakeWxt({
hooks: createHooks(),
config: {
imports: false,
},
});
addImportPreset(wxt, preset);
await wxt.hooks.callHook('ready', wxt);
expect(wxt.config.imports).toBe(false);
});
});
});
@@ -4,9 +4,10 @@ import { getEntrypointName } from '~/core/utils/entrypoints';
import { parseHTML } from 'linkedom';
import { dirname, relative, resolve } from 'node:path';
import { normalizePath } from '~/core/utils/paths';
import { murmurHash } from 'ohash';
// Cache the preamble script for all devHtmlPrerender plugins, not just one
let reactRefreshPreamble = '';
// Stored outside the plugin to effect all instances of the devHtmlPrerender plugin.
const inlineScriptContents: Record<number, string> = {};
/**
* Pre-renders the HTML entrypoints when building the extension to connect to the dev server.
@@ -20,8 +21,9 @@ export function devHtmlPrerender(
config.wxtModuleDir,
'dist/virtual/reload-html.js',
);
const virtualReactRefreshId = '@wxt/virtual-react-refresh';
const resolvedVirtualReactRefreshId = '\0' + virtualReactRefreshId;
const virtualInlineScript = 'virtual:wxt-inline-script';
const resolvedVirtualInlineScript = '\0' + virtualInlineScript;
return [
{
@@ -76,22 +78,22 @@ export function devHtmlPrerender(
const serverHtml = await server.transformHtml(url, html, originalUrl);
const { document } = parseHTML(serverHtml);
// React pages include a preamble as an unsafe-inline type="module" script to enable fast refresh, as shown here:
// https://github.com/wxt-dev/wxt/issues/157#issuecomment-1756497616
// Since unsafe-inline scripts are blocked by MV3 CSPs, we need to virtualize it.
const reactRefreshScript = Array.from(
document.querySelectorAll('script[type=module]'),
).find((script) => script.innerHTML.includes('@react-refresh'));
if (reactRefreshScript) {
// Save preamble to serve from server
reactRefreshPreamble = reactRefreshScript.innerHTML;
// Replace inline script with virtual module served via dev server.
// Extension CSP blocks inline scripts, so that's why we're pulling them
// out.
const inlineScripts = document.querySelectorAll('script:not([src])');
inlineScripts.forEach((script) => {
// Save the text content for later
const textContent = script.textContent ?? '';
const hash = murmurHash(textContent);
inlineScriptContents[hash] = textContent;
// Replace unsafe inline script
const virtualScript = document.createElement('script');
virtualScript.type = 'module';
virtualScript.src = `${server.origin}/${virtualReactRefreshId}`;
reactRefreshScript.replaceWith(virtualScript);
}
virtualScript.src = `${server.origin}/@id/${virtualInlineScript}?${hash}`;
script.replaceWith(virtualScript);
});
// Change /@vite/client -> http://localhost:3000/@vite/client
const viteClientScript = document.querySelector<HTMLScriptElement>(
@@ -112,18 +114,25 @@ export function devHtmlPrerender(
name: 'wxt:virtualize-react-refresh',
apply: 'serve',
resolveId(id) {
if (id === `/${virtualReactRefreshId}`) {
return resolvedVirtualReactRefreshId;
// Resolve inline scripts
if (id.startsWith(virtualInlineScript)) {
return '\0' + id;
}
// Ignore chunk contents when pre-rendering
// Ignore chunks during HTML file pre-rendering
if (id.startsWith('/chunks/')) {
return '\0noop';
}
},
load(id) {
if (id === resolvedVirtualReactRefreshId) {
return reactRefreshPreamble;
// 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];
}
// Ignore chunks during HTML file pre-rendering
if (id === '\0noop') {
return '';
}
@@ -49,7 +49,10 @@ try {
const { document } = parseHTML(html);
const script = document.createElement('script');
script.type = 'module';
script.src = 'virtual:wxt-html-plugins';
script.src =
config.command === 'serve'
? `http://${config.dev.server?.hostname}:${config.dev.server?.port}/@id/${virtualHtmlModuleId}`
: virtualHtmlModuleId;
if (document.head == null) {
const newHead = document.createElement('head');
document.documentElement.prepend(newHead);
@@ -1,6 +1,6 @@
{
"name": "yarn-ls",
"packageManager": "yarn@1.22.19",
"packageManager": "yarn@1.22.22",
"dependencies": {
"mime-types": "2.1.35"
},
@@ -204,6 +204,16 @@ async function writeMainDeclarationFile(references: string[]): Promise<string> {
(ref) =>
`/// <reference types="./${normalizePath(relative(dir, ref))}" />`,
),
// Add references to modules installed from NPM to the TS project so
// their type augmentation can update InlineConfig correctly. Local
// modules defined in <root>/modules are already apart of the project, so
// we don't need to add them.
...wxt.config.modules
.filter(
(module) => module.type === 'node_module' && module.configKey != null,
)
.map((module) => `/// <reference types="${module.id}" />`),
].join('\n') + '\n',
);
return filePath;
@@ -11,6 +11,7 @@ import {
Logger,
WxtCommand,
WxtModule,
WxtModuleWithMetadata,
} from '~/types';
import path from 'node:path';
import { createFsCache } from '~/core/utils/cache';
@@ -380,15 +381,21 @@ export async function mergeBuilderConfig(
export async function resolveWxtModules(
modulesDir: string,
modules: string[] = [],
): Promise<WxtModule<any>[]> {
// Resolve NPM packages
const npmModules = await Promise.all(
): Promise<WxtModuleWithMetadata<any>[]> {
// Resolve node_modules modules
const npmModules = await Promise.all<WxtModuleWithMetadata<any>>(
modules.map(async (moduleId) => {
const mod = await import(/* @vite-ignore */ moduleId);
const mod: { default: WxtModule<any> } = await import(
/* @vite-ignore */ moduleId
);
if (mod.default == null) {
throw Error('Module missing default export: ' + moduleId);
}
return mod.default;
return {
...mod.default,
type: 'node_module',
id: moduleId,
};
}),
);
@@ -397,10 +404,11 @@ export async function resolveWxtModules(
cwd: modulesDir,
onlyFiles: true,
}).catch(() => []);
const localModules = await Promise.all(
const localModules = await Promise.all<WxtModuleWithMetadata<any>>(
localModulePaths.map(async (file) => {
const absolutePath = normalizePath(path.resolve(modulesDir, file));
const { config } = await loadConfig<WxtModule<any>>({
configFile: path.resolve(modulesDir, file),
configFile: absolutePath,
globalRc: false,
rcFile: false,
packageJson: false,
@@ -413,10 +421,12 @@ export async function resolveWxtModules(
);
// Add name based on filename
config.name ??= file;
return config;
return {
...config,
type: 'local',
id: absolutePath,
};
}),
);
// Execute modules
return [...npmModules, ...localModules];
}
+47 -1
View File
@@ -13,6 +13,10 @@ import type {
import * as vite from 'vite';
import glob from 'fast-glob';
import { resolve } from 'node:path';
import type { UnimportOptions } from 'unimport';
// Re-export to prevent TS2742 type errors
export { WxtModule };
export function defineWxtModule<TOptions extends WxtModuleOptions>(
module: WxtModule<TOptions> | WxtModuleSetup<TOptions>,
@@ -123,8 +127,50 @@ export function addViteConfig(
* addWxtPlugin(wxt, "wxt-module-analytics/client-plugin");
* });
*/
export function addWxtPlugin(wxt: Wxt, plugin: string) {
export function addWxtPlugin(wxt: Wxt, plugin: string): void {
wxt.hooks.hook('ready', (wxt) => {
wxt.config.plugins.push(plugin);
});
}
/**
* Add an Unimport preset ([built-in](https://github.com/unjs/unimport?tab=readme-ov-file#built-in-presets),
* [custom](https://github.com/unjs/unimport?tab=readme-ov-file#custom-presets),
* or [auto-scanned](https://github.com/unjs/unimport?tab=readme-ov-file#exports-auto-scan)),
* to the project's list of auto-imported utilities.
*
* Some things to note:
* - This function will only de-duplicate built-in preset names. It will not
* stop you adding duplicate custom or auto-scanned presets.
* - If the project has disabled imports, this function has no effect.
*
* @param wxt The wxt instance provided by the module's setup function.
* @param preset The preset to add to the project.
*
* @example
* export default defineWxtModule((wxt) => {
* // Built-in preset:
* addImportPreset(wxt, "vue");
* // Custom preset:
* addImportPreset(wxt, {
* from: "vue",
* imports: ["ref", "reactive", ...],
* });
* // Auto-scanned preset:
* addImportPreset(wxt, { package: "vue" });
* });
*/
export function addImportPreset(
wxt: Wxt,
preset: UnimportOptions['presets'][0],
): void {
wxt.hooks.hook('ready', (wxt) => {
if (!wxt.config.imports) return;
wxt.config.imports.presets ??= [];
// De-dupelicate built-in named presets
if (wxt.config.imports.presets.includes(preset)) return;
wxt.config.imports.presets.push(preset);
});
}
+8 -2
View File
@@ -1185,7 +1185,7 @@ export interface ResolvedConfig {
reloadCommand: string | false;
};
hooks: NestedHooks<WxtHooks>;
modules: WxtModule<any>[];
modules: WxtModuleWithMetadata<any>[];
/**
* An array of string to import plugins from. These paths should be
* resolvable by vite, and they should `export default defineWxtPlugin(...)`.
@@ -1300,7 +1300,7 @@ export type WxtModuleOptions = Record<string, any>;
export type WxtModuleSetup<TOptions extends WxtModuleOptions> = (
wxt: Wxt,
moduleOptions: TOptions,
moduleOptions?: TOptions,
) => void | Promise<void>;
export interface WxtModule<TOptions extends WxtModuleOptions> {
@@ -1325,6 +1325,12 @@ export interface WxtModule<TOptions extends WxtModuleOptions> {
setup?: WxtModuleSetup<TOptions>;
}
export interface WxtModuleWithMetadata<TOptions extends WxtModuleOptions>
extends WxtModule<TOptions> {
type: 'local' | 'node_module';
id: string;
}
export interface ResolvedPublicFile {
/**
* The absolute path to the file that will be copied to the output directory.
+2125 -856
View File
File diff suppressed because it is too large Load Diff
+133
View File
@@ -0,0 +1,133 @@
//
// Build all workspace packages, or only dependencies of a specific package.
// Kind of a simple version of nx/turborepo, but we can keep using PNPM to run
// all commands.
//
// Usage:
// pnpm tsx scripts/build-deps.ts # Builds all packages in repo
// pnpm tsx scripts/build-deps.ts <packageName> # Builds only dependencies of <packageName>
//
import glob from 'fast-glob';
import { DepGraph } from 'dependency-graph';
import fs from 'fs-extra';
import YAML from 'yaml';
import { execa } from 'execa';
import consola from 'consola';
import { hashFile, hash } from 'hasha';
import { resolve } from 'node:path';
// Quick hack to prevent recursive calls to this script. If it's being called
// from another instance of this script, the parent instance is already
// preforming this build, so it can be skipped.
if (process.env.BUILD_DEPS) process.exit(0);
process.env.BUILD_DEPS = 'true';
// Parse args
const packageToBuild = process.argv[2];
if (packageToBuild == null) {
consola.info('Building all packages...');
} else {
consola.info(`Building dependencies of \`${packageToBuild}\``);
}
// Build graph
const workspace: { packages: string[] } = YAML.parse(
await fs.readFile('pnpm-workspace.yaml', 'utf8'),
);
const packageDirs = await glob(workspace.packages, { onlyDirectories: true });
const graph = new DepGraph<Record<string, any>>();
// Add all packages to chart
for (const packageDir of packageDirs) {
try {
const packageJson = await fs.readJson(`${packageDir}/package.json`);
graph.addNode(packageJson.name, { ...packageJson, dir: packageDir });
} catch {
// Package missing package.json, ignore it
}
}
// Add dependencies between packages
graph.entryNodes().forEach((packageName) => {
const packageJson = graph.getNodeData(packageName);
[
...Object.entries<string>(packageJson.dependencies ?? {}),
...Object.entries<string>(packageJson.devDependencies ?? {}),
].forEach(([dep, version]) => {
if (version !== 'workspace:*') return;
graph.addDependency(packageName, dep);
});
});
function printGraph(graph: DepGraph<any>) {
consola.debug('Dependency Graph:');
function printNode(node: string, level = 0) {
consola.debug(`${''.padStart(level * 2, ' ')}- \`${node}\``);
graph.dependenciesOf(node).forEach((dep) => printNode(dep, level + 1));
}
graph.entryNodes().forEach((entry) => printNode(entry));
}
printGraph(graph);
if (packageToBuild) {
// Remove nodes not associated with the package to build
graph.entryNodes().forEach((entry) => {
if (entry !== packageToBuild) graph.removeNode(entry);
});
}
// Get order
const buildOrder = graph.overallOrder().filter(
// Remove packageToBuild if provided
(packageName) => packageName !== packageToBuild,
);
consola.info('Build order:', buildOrder);
// Build dependencies of a package
async function hashDir(dir: string): Promise<string> {
const files = await glob('**/*', {
ignore: [
'**/dist/**',
'**/node_modules/**',
'**/__tests__/**',
'**/e2e/**',
'CHANGELOG.md',
'typedoc.json',
'vitest.*.ts',
],
cwd: dir,
});
const hashes = await Promise.all(
files.sort().map(async (file) => {
const hash = await hashFile(resolve(dir, file), { algorithm: 'md5' });
return `${hash}-${file}`;
}),
);
consola.debug(hashes.join('\n'));
return await hash(hashes.join('\n'), { algorithm: 'md5' });
}
async function buildPackage(packageName: string): Promise<void> {
const packageJson = graph.getNodeData(packageName);
const hash = await hashDir(packageJson.dir);
consola.debug('Directory hash:', hash);
const cacheDir = resolve('.cache', packageJson.dir, hash);
const outputDir = resolve(packageJson.dir, 'dist');
if (await fs.pathExists(cacheDir)) {
await fs.ensureDir(outputDir);
await fs.copy(cacheDir, outputDir);
consola.success(`\`${packageName}\` cached`);
} else {
await execa('pnpm', ['--filter', packageName, 'build'], {
stdio: 'inherit',
});
await fs.ensureDir(cacheDir);
await fs.copy(outputDir, cacheDir);
}
}
try {
for (const packageName of buildOrder) {
await buildPackage(packageName);
}
} catch (err) {
consola.error(err);
process.exit(1);
}
+4 -3
View File
@@ -40,13 +40,14 @@ await execa('pnpm', ['version', bumpType], {
});
const updatedPkgJson = await fs.readJson(pkgJsonPath);
const newVersion: string = updatedPkgJson.version;
const newTag = getPkgTag(pkg, newVersion);
consola.info('Bump:', { currentVersion, bumpType, newVersion });
// Generate changelog
const versionChangelog = await generateMarkDown(commits, {
...config,
from: currentVersion,
to: newVersion,
from: prevTag,
to: newTag,
});
const versionChangelogBody = versionChangelog
.split('\n')
@@ -80,5 +81,5 @@ await execa('git', [
'-m',
`chore(release): ${pkgName} v${newVersion}`,
]);
await execa('git', ['tag', getPkgTag(pkg, newVersion)]);
await execa('git', ['tag', newTag]);
consola.success('Committed version and changelog');
+12 -8
View File
@@ -27,14 +27,18 @@ config.tokens.github = process.env.GITHUB_TOKEN;
// Update releases
for (const release of releases) {
const tag = getPkgTag(pkg, release.version);
const existing = await getGithubReleaseByTag(config, tag);
if (existing.body !== release.body) {
await updateGithubRelease(config, existing.id!, {
tag_name: tag,
name: `${pkgName} v${release.version}`,
body: release.body,
});
try {
const existing = await getGithubReleaseByTag(config, tag);
if (existing.body !== release.body) {
await updateGithubRelease(config, existing.id!, {
tag_name: tag,
name: `${pkgName} v${release.version}`,
body: release.body,
});
}
consola.success(`Synced \`${tag}\``);
} catch (err) {
consola.fail(`\`${tag}\``, err);
}
consola.success(`Synced \`${tag}\``);
}
consola.success('Done');
+4
View File
@@ -0,0 +1,4 @@
// https://github.com/antfu-collective/taze?tab=readme-ov-file#config-file
export default {
exclude: ['typedoc', 'typedoc-plugin-markdown', 'typedoc-vitepress-theme'],
};
+7 -7
View File
@@ -15,14 +15,14 @@
"postinstall": "wxt prepare"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
"@vitejs/plugin-react": "^4.2.1",
"typescript": "^5.3.3",
"wxt": "^0.18.0"
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"typescript": "^5.4.5",
"wxt": "^0.18.6"
}
}
+4 -4
View File
@@ -15,11 +15,11 @@
"postinstall": "wxt prepare"
},
"dependencies": {
"solid-js": "^1.8.7"
"solid-js": "^1.8.17"
},
"devDependencies": {
"typescript": "^5.3.3",
"vite-plugin-solid": "^2.8.0",
"wxt": "^0.18.0"
"typescript": "^5.4.5",
"vite-plugin-solid": "^2.10.2",
"wxt": "^0.18.6"
}
}
+7 -7
View File
@@ -14,12 +14,12 @@
"postinstall": "wxt prepare"
},
"devDependencies": {
"@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.18.0"
"@sveltejs/vite-plugin-svelte": "^3.1.1",
"@tsconfig/svelte": "^5.0.4",
"svelte": "^4.2.18",
"svelte-check": "^3.8.0",
"tslib": "^2.6.3",
"typescript": "^5.4.5",
"wxt": "^0.18.6"
}
}
+2 -2
View File
@@ -15,7 +15,7 @@
"postinstall": "wxt prepare"
},
"devDependencies": {
"typescript": "^5.3.3",
"wxt": "^0.18.0"
"typescript": "^5.4.5",
"wxt": "^0.18.6"
}
}
+5 -5
View File
@@ -15,12 +15,12 @@
"postinstall": "wxt prepare"
},
"dependencies": {
"vue": "^3.4.0"
"vue": "^3.4.27"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.1",
"typescript": "^5.3.3",
"vue-tsc": "^2.0.6",
"wxt": "^0.18.0"
"@vitejs/plugin-vue": "^5.0.5",
"typescript": "^5.4.5",
"vue-tsc": "^2.0.21",
"wxt": "^0.18.6"
}
}