Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e60f37ec5 | |||
| 6f901b32eb | |||
| 927aca612e | |||
| 2dcdae91eb | |||
| eb758bdeb8 | |||
| 5acf51af9d | |||
| f9718a1b71 | |||
| cf7f23d4c3 | |||
| 62ecb6f41e | |||
| fc45c37f22 | |||
| 68874e607e | |||
| 35865adcb2 | |||
| 3b63a51475 | |||
| d32e59e38f | |||
| dab8efa140 |
@@ -1,5 +1,57 @@
|
||||
# Changelog
|
||||
|
||||
## v0.15.0
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.14.7...v0.15.0)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- **zip:** ⚠️ Add `includeSources` and rename `ignoredSources` to `excludeSources` ([#378](https://github.com/wxt-dev/wxt/pull/378))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Generate missing sourcemap in `wxt:unimport` plugin ([#381](https://github.com/wxt-dev/wxt/pull/381))
|
||||
- ⚠️ Move browser constants to `import.meta.env` ([#380](https://github.com/wxt-dev/wxt/pull/380))
|
||||
- Enable inline sourcemaps by default during development ([#382](https://github.com/wxt-dev/wxt/pull/382))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Fix typo ([f9718a1](https://github.com/wxt-dev/wxt/commit/f9718a1))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Update contributor docs ([eb758bd](https://github.com/wxt-dev/wxt/commit/eb758bd))
|
||||
|
||||
#### ⚠️ Breaking Changes
|
||||
|
||||
- **zip:** ⚠️ Add `includeSources` and rename `ignoredSources` to `excludeSources` ([#378](https://github.com/wxt-dev/wxt/pull/378))
|
||||
- ⚠️ Move browser constants to `import.meta.env` ([#380](https://github.com/wxt-dev/wxt/pull/380))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Nenad Novaković
|
||||
|
||||
## v0.14.7
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.14.6...v0.14.7)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Improve error messages when importing and building entrypoints ([3b63a51](https://github.com/wxt-dev/wxt/commit/3b63a51))
|
||||
- **storage:** Throw better error message when importing outside a extension environment ([35865ad](https://github.com/wxt-dev/wxt/commit/35865ad))
|
||||
- Upgrade `web-ext-run` ([62ecb6f](https://github.com/wxt-dev/wxt/commit/62ecb6f))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Add `matches` to content script examples ([dab8efa](https://github.com/wxt-dev/wxt/commit/dab8efa))
|
||||
- Fix incorrect sample code ([#372](https://github.com/wxt-dev/wxt/pull/372))
|
||||
- Document defined constants for the build target ([68874e6](https://github.com/wxt-dev/wxt/commit/68874e6))
|
||||
- Add missing `await` to `createShadowRootUi` examples ([fc45c37](https://github.com/wxt-dev/wxt/commit/fc45c37))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- 東奈比 ([@dongnaebi](http://github.com/dongnaebi))
|
||||
|
||||
## v0.14.6
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.14.5...v0.14.6)
|
||||
|
||||
+9
-1
@@ -57,9 +57,17 @@ pnpm test
|
||||
pnpm docs:dev
|
||||
```
|
||||
|
||||
## Updating Docs
|
||||
|
||||
Documentation is written with VitePress, and is located in the `docs/` directory.
|
||||
|
||||
The API reference is generated from JSDoc comments in the source code. If there's a typo or change you want to make in there, you'll need to update the source code instead of a file in the `docs/` directory.
|
||||
|
||||
## Testing
|
||||
|
||||
WXT has unit and E2E tests. When making a change or adding a feature, make sure to update the tests or add new ones.
|
||||
WXT has unit and E2E tests. When making a change or adding a feature, make sure to update the tests or add new ones, if they exist.
|
||||
|
||||
> If they don't exist, feel free to create them, but that's a lot for a one-time contributor. A maintainer might add them to your PR though.
|
||||
|
||||
To run tests for a specific file, add the filename at the end of the test command:
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ export default defineBackground(() => {
|
||||
console.log(browser.runtime.id);
|
||||
logId();
|
||||
console.log({
|
||||
browser: __BROWSER__,
|
||||
chrome: __IS_CHROME__,
|
||||
firefox: __IS_FIREFOX__,
|
||||
manifestVersion: __MANIFEST_VERSION__,
|
||||
browser: import.meta.env.BROWSER,
|
||||
chrome: import.meta.env.CHROME,
|
||||
firefox: import.meta.env.FIREFOX,
|
||||
manifestVersion: import.meta.env.MANIFEST_VERSION,
|
||||
messages,
|
||||
});
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ Integrated content script UIs are injected alongside the content of a page. This
|
||||
```ts [Vanilla]
|
||||
// entrypoints/example-ui.content.ts
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
|
||||
main(ctx) {
|
||||
const ui = createIntegratedUi(ctx, {
|
||||
position: 'inline',
|
||||
@@ -45,6 +47,8 @@ import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
|
||||
main(ctx) {
|
||||
const ui = createIntegratedUi(ctx, {
|
||||
position: 'inline',
|
||||
@@ -73,6 +77,8 @@ import ReactDOM from 'react-dom/client';
|
||||
import App from './App.tsx';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
|
||||
main(ctx) {
|
||||
const ui = createIntegratedUi(ctx, {
|
||||
position: 'inline',
|
||||
@@ -100,6 +106,8 @@ export default defineContentScript({
|
||||
import App from './App.svelte';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
|
||||
main(ctx) {
|
||||
const ui = createIntegratedUi(ctx, {
|
||||
position: 'inline',
|
||||
@@ -128,6 +136,8 @@ export default defineContentScript({
|
||||
import { render } from 'solid-js/web';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
|
||||
main(ctx) {
|
||||
const ui = createIntegratedUi(ctx, {
|
||||
position: 'inline',
|
||||
@@ -174,6 +184,7 @@ To use `createShadowRootUi`, follow these steps:
|
||||
import './style.css';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
// 2. Set cssInjectionMode
|
||||
cssInjectionMode: 'ui',
|
||||
|
||||
@@ -182,7 +193,7 @@ export default defineContentScript({
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
name: 'example-ui',
|
||||
anchor: '#anchor',
|
||||
type: 'inline',
|
||||
position: 'inline',
|
||||
onMount(container) {
|
||||
// Define how your UI will be mounted inside the container
|
||||
const app = document.createElement('p');
|
||||
@@ -204,6 +215,7 @@ import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
// 2. Set cssInjectionMode
|
||||
cssInjectionMode: 'ui',
|
||||
|
||||
@@ -212,7 +224,7 @@ export default defineContentScript({
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
name: 'example-ui',
|
||||
anchor: '#anchor',
|
||||
type: 'inline',
|
||||
position: 'inline',
|
||||
onMount: (container) => {
|
||||
// Define how your UI will be mounted inside the container
|
||||
const app = createApp(App);
|
||||
@@ -238,12 +250,13 @@ import ReactDOM from 'react-dom/client';
|
||||
import App from './App.tsx';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
// 2. Set cssInjectionMode
|
||||
cssInjectionMode: 'ui',
|
||||
|
||||
main(ctx) {
|
||||
async main(ctx) {
|
||||
// 3. Define your UI
|
||||
const ui = createShadowRootUi(ctx, {
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
name: 'example-ui',
|
||||
position: 'inline',
|
||||
anchor: '#anchor',
|
||||
@@ -271,12 +284,13 @@ import './style.css';
|
||||
import App from './App.svelte';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
// 2. Set cssInjectionMode
|
||||
cssInjectionMode: 'ui',
|
||||
|
||||
main(ctx) {
|
||||
async main(ctx) {
|
||||
// 3. Define your UI
|
||||
const ui = createShadowRootUi(ctx, {
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
name: 'example-ui',
|
||||
position: 'inline',
|
||||
anchor: '#anchor',
|
||||
@@ -305,12 +319,13 @@ import './style.css';
|
||||
import { render } from 'solid-js/web';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
// 2. Set cssInjectionMode
|
||||
cssInjectionMode: 'ui',
|
||||
|
||||
main(ctx) {
|
||||
async main(ctx) {
|
||||
// 3. Define your UI
|
||||
const ui = createShadowRootUi(ctx, {
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
name: 'example-ui',
|
||||
position: 'inline',
|
||||
anchor: '#anchor',
|
||||
@@ -377,13 +392,14 @@ WXT provides a helper function, [`createIframeUi`](/api/wxt/client/functions/cre
|
||||
|
||||
```ts
|
||||
export default defineContentScript({
|
||||
// ...
|
||||
matches: ['<all_urls>'],
|
||||
|
||||
async main(ctx) {
|
||||
// Define the UI
|
||||
const ui = await createIframeUi(ctx, {
|
||||
page: '/example-iframe.html',
|
||||
anchor: '#anchor',
|
||||
type: 'inline',
|
||||
position: 'inline',
|
||||
onMount: (wrapper, iframe) => {
|
||||
// Add styles to the iframe like width
|
||||
iframe.width = 123;
|
||||
|
||||
@@ -17,11 +17,9 @@ Separate build targets are written to their own output directories:
|
||||
|
||||
To build for a specific browser, pass the `-b --browser` flag from the CLI:
|
||||
|
||||
```
|
||||
|
||||
```sh
|
||||
wxt --browser firefox
|
||||
wxt build --browser firefox
|
||||
|
||||
```
|
||||
|
||||
By default, it will build for `chrome`. When excluding the [manifest version flags](#target-manifest-version), it will default to the commonly accepted manifest version for that browser.
|
||||
@@ -112,3 +110,24 @@ export default defineContentScript({
|
||||
:::warning
|
||||
Only `defineBackground` and `defineContentScript` support per-browser options right now.
|
||||
:::
|
||||
|
||||
## Runtime
|
||||
|
||||
To determine the browser or manifest version at runtime, you can use any of the below variables:
|
||||
|
||||
- `import.meta.env.BROWSER`: A string, the target browser, usually equal to the `--browser` flag
|
||||
- `import.meta.env.MANIFEST_VERSION`: A number, either `2` or `3`, depending on the manifest version targetted
|
||||
- `import.meta.env.CHROME`: A boolean equivalent to `import.meta.env.BROWSER === "chrome"`
|
||||
- `import.meta.env.FIREFOX`: A boolean equivalent to `import.meta.env.BROWSER === "firefox"`
|
||||
- `import.meta.env.EDGE`: A boolean equivalent to `import.meta.env.BROWSER === "edge"`
|
||||
- `import.meta.env.SAFARI`: A boolean equivalent to `import.meta.env.BROWSER === "safari"`
|
||||
- `import.meta.env.OPERA`: A boolean equivalent to `import.meta.env.BROWSER === "opera"`
|
||||
- `import.meta.env.COMMAND`: A string, `"serve"` when running `wxt` for development or `"build"` in all other cases.
|
||||
|
||||
:::info
|
||||
These variables are constants defined at build time based on the build target. They do not actually detect which browser the code is running in.
|
||||
|
||||
For example, if you build for `--browser chrome` and publish it on Edge, `import.meta.env.BROWSER` will be `"chrome"`, not `"edge"`. You have to build a separate ZIP for `--browser edge` before `import.meta.env.BROWSER` will be `"edge"`.
|
||||
|
||||
If you need to know the actual browser your code is being ran on, you should use a [user agent parser](https://www.npmjs.com/package/ua-parser-js).
|
||||
:::
|
||||
|
||||
@@ -19,7 +19,7 @@ If you want to try to use a different framework for unit tests, you will need to
|
||||
- **Auto-imports**: Add `unimport` to your test environment or disable them by setting `imports: false` in your `wxt.config.ts` file
|
||||
- **`browser` mock**: Mock the `webextension-polyfill` module globally with `wxt/dist/virtual/mock-browser.js`
|
||||
- **[Remote Code Bundling](/guide/remote-code)**: If you use it, configure your environment to handle the `url:` module prefix
|
||||
- **Global Variables**: If you consume them, manually define globals provided by WXT (like `__BROWSER__`) by adding them to the global scope before accessing them (`globalThis.__BROWSER__ = "chrome"`)
|
||||
- **Global Variables**: If you consume them, manually define globals provided by WXT (like `import.meta.env.BROWSER`) by adding them to the global scope before accessing them (`import.meta.env.BROWSER = "chrome"`)
|
||||
- **Import paths**: If you use the `@/` or `~/` path aliases, add them to your test environment
|
||||
|
||||
[Here's how Vitest is configured](https://github.com/wxt-dev/wxt/blob/main/src/testing/wxt-vitest-plugin.ts) for reference.
|
||||
|
||||
@@ -14,16 +14,19 @@ describe('TypeScript Project', () => {
|
||||
----------------------------------------
|
||||
// Generated by wxt
|
||||
export {}
|
||||
declare global {
|
||||
const __MANIFEST_VERSION__: 2 | 3;
|
||||
const __BROWSER__: string;
|
||||
const __IS_CHROME__: boolean;
|
||||
const __IS_FIREFOX__: boolean;
|
||||
const __IS_SAFARI__: boolean;
|
||||
const __IS_EDGE__: boolean;
|
||||
const __IS_OPERA__: boolean;
|
||||
const __COMMAND__: "build" | "serve";
|
||||
const __ENTRYPOINT__: string;
|
||||
interface ImportMetaEnv {
|
||||
readonly MANIFEST_VERSION: 2 | 3;
|
||||
readonly BROWSER: string;
|
||||
readonly CHROME: boolean;
|
||||
readonly FIREFOX: boolean;
|
||||
readonly SAFARI: boolean;
|
||||
readonly EDGE: boolean;
|
||||
readonly OPERA: boolean;
|
||||
readonly COMMAND: "build" | "serve";
|
||||
readonly ENTRYPOINT: string;
|
||||
}
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv
|
||||
}
|
||||
"
|
||||
`);
|
||||
@@ -133,7 +136,7 @@ describe('TypeScript Project', () => {
|
||||
options?: GetMessageOptions,
|
||||
): string;
|
||||
/**
|
||||
*
|
||||
* No message description.
|
||||
*
|
||||
* "<browser.i18n.getUiLocale()>"
|
||||
*/
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wxt",
|
||||
"type": "module",
|
||||
"version": "0.14.6",
|
||||
"version": "0.15.0",
|
||||
"description": "Next gen framework for developing web extensions",
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
@@ -135,7 +135,7 @@
|
||||
"rollup-plugin-visualizer": "^5.9.2",
|
||||
"unimport": "^3.4.0",
|
||||
"vite": "^5.0.0",
|
||||
"web-ext-run": "^0.1.0",
|
||||
"web-ext-run": "^0.1.2",
|
||||
"webextension-polyfill": "^0.10.0",
|
||||
"zip-dir": "^2.0.0"
|
||||
},
|
||||
|
||||
Generated
+33
-24
@@ -105,8 +105,8 @@ importers:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.5(@types/node@20.10.3)(sass@1.69.5)
|
||||
web-ext-run:
|
||||
specifier: ^0.1.0
|
||||
version: 0.1.0
|
||||
specifier: ^0.1.2
|
||||
version: 0.1.2
|
||||
webextension-polyfill:
|
||||
specifier: ^0.10.0
|
||||
version: 0.10.0
|
||||
@@ -412,8 +412,8 @@ packages:
|
||||
'@babel/types': 7.23.5
|
||||
dev: true
|
||||
|
||||
/@babel/runtime@7.22.11:
|
||||
resolution: {integrity: sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==}
|
||||
/@babel/runtime@7.23.9:
|
||||
resolution: {integrity: sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
regenerator-runtime: 0.14.0
|
||||
@@ -442,8 +442,8 @@ packages:
|
||||
engines: {node: '>= 0.10.4'}
|
||||
dev: false
|
||||
|
||||
/@devicefarmer/adbkit@3.2.5:
|
||||
resolution: {integrity: sha512-+J479WWZW3GU3t40flicDfiDrFz6vpiy2RcBQPEhFcs/3La9pOtr4Bgz2Q02E4luUG2RAL068rqIkKNUTy3tZw==}
|
||||
/@devicefarmer/adbkit@3.2.6:
|
||||
resolution: {integrity: sha512-8lO1hSeTgtxcOHhp4tTWq/JaOysp5KNbbyFoxNEBnwkCDZu/Bji3ZfOaG++Riv9jN6c9bgdLBOZqJTC5VJPRKQ==}
|
||||
engines: {node: '>= 0.10.4'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
@@ -2380,8 +2380,8 @@ packages:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
|
||||
/firefox-profile@4.3.2:
|
||||
resolution: {integrity: sha512-/C+Eqa0YgIsQT2p66p7Ygzqe7NlE/GNTbhw2SBCm5V3OsWDPITNdTPEcH2Q2fe7eMpYYNPKdUcuVioZBZiR6kA==}
|
||||
/firefox-profile@4.5.0:
|
||||
resolution: {integrity: sha512-goE2XxbmYVSafvCjcy64/AK3xOr14HCUCD4+TpYWEIMy4nrJfNAacLGzwqKwZhCW0hHI2TYMGH+G/YBvOE8L6g==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
adm-zip: 0.5.10
|
||||
@@ -2422,6 +2422,15 @@ packages:
|
||||
universalify: 2.0.0
|
||||
dev: false
|
||||
|
||||
/fs-extra@11.2.0:
|
||||
resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
|
||||
engines: {node: '>=14.14'}
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
jsonfile: 6.1.0
|
||||
universalify: 2.0.0
|
||||
dev: false
|
||||
|
||||
/fs-extra@9.0.1:
|
||||
resolution: {integrity: sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -2467,8 +2476,8 @@ packages:
|
||||
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
||||
dev: true
|
||||
|
||||
/fx-runner@1.3.0:
|
||||
resolution: {integrity: sha512-5b37H4GCyhF+Nf8xk9mylXoDq4wb7pbGAXxlCXp/631UTeeZomWSYcEGXumY4wk8g2QAqjPMGdWW+RbNt8PUcA==}
|
||||
/fx-runner@1.4.0:
|
||||
resolution: {integrity: sha512-rci1g6U0rdTg6bAaBboP7XdRu01dzTAaKXxFf+PUqGuCv6Xu7o8NZdY1D5MvKGIjb6EdS1g3VlXOgksir1uGkg==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
commander: 2.9.0
|
||||
@@ -3772,8 +3781,8 @@ packages:
|
||||
json-parse-better-errors: 1.0.2
|
||||
dev: true
|
||||
|
||||
/parse-json@7.1.0:
|
||||
resolution: {integrity: sha512-ihtdrgbqdONYD156Ap6qTcaGcGdkdAxodO1wLqQ/j7HP1u2sFYppINiq4jyC8F+Nm+4fVufylCV00QmkTHkSUg==}
|
||||
/parse-json@7.1.1:
|
||||
resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==}
|
||||
engines: {node: '>=16'}
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.22.5
|
||||
@@ -5186,24 +5195,24 @@ packages:
|
||||
graceful-fs: 4.2.11
|
||||
dev: false
|
||||
|
||||
/web-ext-run@0.1.0:
|
||||
resolution: {integrity: sha512-42ezvTBirf1v2hw0q4FqYvAzh39bCn3cMQojTLlaE5Y8DWebVkRGdd0jdSJRzPkB5jZa0CHfnqe8gx6oUllqyw==}
|
||||
engines: {node: '>=16.0.0', npm: '>=8.0.0'}
|
||||
/web-ext-run@0.1.2:
|
||||
resolution: {integrity: sha512-VygO7lg10keonbku5Lbi21zEz1k91odkW+c6YB5DGb+mITcRMVM2zr/tJ+Suh6wxNUOOFNbinoqDlSUWdxt6YQ==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.11
|
||||
'@devicefarmer/adbkit': 3.2.5
|
||||
'@babel/runtime': 7.23.9
|
||||
'@devicefarmer/adbkit': 3.2.6
|
||||
bunyan: 1.8.15
|
||||
chrome-launcher: 0.15.1
|
||||
debounce: 1.2.1
|
||||
es6-error: 4.1.1
|
||||
firefox-profile: 4.3.2
|
||||
fs-extra: 11.1.1
|
||||
fx-runner: 1.3.0
|
||||
firefox-profile: 4.5.0
|
||||
fs-extra: 11.2.0
|
||||
fx-runner: 1.4.0
|
||||
mkdirp: 1.0.4
|
||||
multimatch: 6.0.0
|
||||
mz: 2.7.0
|
||||
node-notifier: 10.0.1
|
||||
parse-json: 7.1.0
|
||||
parse-json: 7.1.1
|
||||
promise-toolbox: 0.21.0
|
||||
source-map-support: 0.5.21
|
||||
strip-bom: 5.0.0
|
||||
@@ -5211,7 +5220,7 @@ packages:
|
||||
tmp: 0.2.1
|
||||
update-notifier: 6.0.2
|
||||
watchpack: 2.4.0
|
||||
ws: 8.13.0
|
||||
ws: 8.16.0
|
||||
zip-dir: 2.0.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
@@ -5364,8 +5373,8 @@ packages:
|
||||
typedarray-to-buffer: 3.1.5
|
||||
dev: false
|
||||
|
||||
/ws@8.13.0:
|
||||
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
|
||||
/ws@8.16.0:
|
||||
resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
|
||||
@@ -15,10 +15,12 @@ export class WxtLocationChangeEvent extends Event {
|
||||
* Returns an event name unique to the extension and content script that's running.
|
||||
*/
|
||||
export function getUniqueEventName(eventName: string): string {
|
||||
// During the build process, __ENTRYPOINT__ is not defined when importing entrypoints to get their
|
||||
// metadata.
|
||||
// During the build process, import.meta.env is not defined when importing
|
||||
// entrypoints to get their metadata.
|
||||
const entrypointName =
|
||||
typeof __ENTRYPOINT__ === 'undefined' ? 'build' : __ENTRYPOINT__;
|
||||
typeof import.meta.env === 'undefined'
|
||||
? 'build'
|
||||
: import.meta.env.ENTRYPOINT;
|
||||
|
||||
return `${browser.runtime.id}:${entrypointName}:${eventName}`;
|
||||
}
|
||||
|
||||
@@ -236,7 +236,9 @@ function mountUi(
|
||||
* Load the CSS for the current entrypoint.
|
||||
*/
|
||||
async function loadCss(): Promise<string> {
|
||||
const url = browser.runtime.getURL(`/content-scripts/${__ENTRYPOINT__}.css`);
|
||||
const url = browser.runtime.getURL(
|
||||
`/content-scripts/${import.meta.env.ENTRYPOINT}.css`,
|
||||
);
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
return await res.text();
|
||||
|
||||
@@ -44,6 +44,10 @@ export async function createViteBuilder(
|
||||
if (config.build.minify == null && wxtConfig.command === 'serve') {
|
||||
config.build.minify = false;
|
||||
}
|
||||
// Enable inline sourcemaps for the dev command (so content scripts have sourcemaps)
|
||||
if (config.build.sourcemap == null && wxtConfig.command === 'serve') {
|
||||
config.build.sourcemap = 'inline';
|
||||
}
|
||||
|
||||
config.plugins ??= [];
|
||||
config.plugins.push(
|
||||
|
||||
@@ -14,7 +14,7 @@ export function entrypointGroupGlobals(
|
||||
const define: vite.InlineConfig['define'] = {};
|
||||
let name = Array.isArray(entrypointGroup) ? 'html' : entrypointGroup.name;
|
||||
for (const global of getEntrypointGlobals(name)) {
|
||||
define[global.name] = JSON.stringify(global.value);
|
||||
define[`import.meta.env.${global.name}`] = JSON.stringify(global.value);
|
||||
}
|
||||
return {
|
||||
define,
|
||||
|
||||
@@ -10,7 +10,7 @@ export function globals(
|
||||
config() {
|
||||
const define: vite.InlineConfig['define'] = {};
|
||||
for (const global of getGlobals(config)) {
|
||||
define[global.name] = JSON.stringify(global.value);
|
||||
define[`import.meta.env.${global.name}`] = JSON.stringify(global.value);
|
||||
}
|
||||
return {
|
||||
define,
|
||||
|
||||
@@ -36,7 +36,11 @@ export function unimport(
|
||||
// Don't transform non-js files
|
||||
if (!ENABLED_EXTENSIONS.has(extname(id))) return;
|
||||
|
||||
return unimport.injectImports(code, id);
|
||||
const injected = await unimport.injectImports(code, id);
|
||||
return {
|
||||
code: injected.code,
|
||||
map: injected.s.generateMap({ hires: 'boundary', source: id }),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,12 +18,15 @@ export async function buildEntrypoints(
|
||||
const steps: BuildStepOutput[] = [];
|
||||
for (let i = 0; i < groups.length; i++) {
|
||||
const group = groups[i];
|
||||
const groupNames = [group]
|
||||
.flat()
|
||||
.map((e) => e.name)
|
||||
.join(pc.dim(', '));
|
||||
spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNames}`;
|
||||
steps.push(await config.builder.build(group));
|
||||
const groupNames = [group].flat().map((e) => e.name);
|
||||
const groupNameColored = groupNames.join(pc.dim(', '));
|
||||
spinner.text =
|
||||
pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNameColored}`;
|
||||
try {
|
||||
steps.push(await config.builder.build(group));
|
||||
} catch (err) {
|
||||
throw Error(`Failed to build ${groupNames.join(', ')}`, { cause: err });
|
||||
}
|
||||
}
|
||||
const publicAssets = await copyPublicDirectory(config);
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ declare module "wxt/browser" {
|
||||
|
||||
const overrides = messages.map((message) => {
|
||||
return ` /**
|
||||
* ${message.description ?? 'No message description.'}
|
||||
* ${message.description || 'No message description.'}
|
||||
*
|
||||
* "${message.message}"
|
||||
*/
|
||||
@@ -164,8 +164,11 @@ async function writeGlobalsDeclarationFile(
|
||||
[
|
||||
'// Generated by wxt',
|
||||
'export {}',
|
||||
'declare global {',
|
||||
...globals.map((global) => ` const ${global.name}: ${global.type};`),
|
||||
'interface ImportMetaEnv {',
|
||||
...globals.map((global) => ` readonly ${global.name}: ${global.type};`),
|
||||
'}',
|
||||
'interface ImportMeta {',
|
||||
' readonly env: ImportMetaEnv',
|
||||
'}',
|
||||
].join('\n') + '\n',
|
||||
);
|
||||
|
||||
@@ -241,8 +241,9 @@ function resolveInternalZipConfig(
|
||||
sourcesTemplate: '{{name}}-{{version}}-sources.zip',
|
||||
artifactTemplate: '{{name}}-{{version}}-{{browser}}.zip',
|
||||
sourcesRoot: root,
|
||||
includeSources: [],
|
||||
...mergedConfig.zip,
|
||||
ignoredSources: [
|
||||
excludeSources: [
|
||||
'**/node_modules',
|
||||
// WXT files
|
||||
'**/web-ext.config.ts',
|
||||
@@ -252,7 +253,7 @@ function resolveInternalZipConfig(
|
||||
'**/__tests__/**',
|
||||
'**/*.+(test|spec).?(c|m)+(j|t)s?(x)',
|
||||
// From user
|
||||
...(mergedConfig.zip?.ignoredSources ?? []),
|
||||
...(mergedConfig.zip?.excludeSources ?? []),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,16 +89,17 @@ export async function importEntrypointFile<T>(
|
||||
const res = await jiti(path);
|
||||
return res.default;
|
||||
} catch (err) {
|
||||
const filePath = relative(config.root, path);
|
||||
if (err instanceof ReferenceError) {
|
||||
// "XXX is not defined" - usually due to WXT removing imports
|
||||
const variableName = err.message.replace(' is not defined', '');
|
||||
const filePath = relative(config.root, path);
|
||||
throw Error(
|
||||
`${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/entrypoints.html#side-effects`,
|
||||
{ cause: err },
|
||||
);
|
||||
} else {
|
||||
throw err;
|
||||
config.logger.error(err);
|
||||
throw Error(`Failed to load entrypoint: ${filePath}`, { cause: err });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,42 +5,42 @@ export function getGlobals(
|
||||
): Array<{ name: string; value: any; type: string }> {
|
||||
return [
|
||||
{
|
||||
name: surroundInUnderscore('MANIFEST_VERSION'),
|
||||
name: 'MANIFEST_VERSION',
|
||||
value: config.manifestVersion,
|
||||
type: `2 | 3`,
|
||||
},
|
||||
{
|
||||
name: surroundInUnderscore('BROWSER'),
|
||||
name: 'BROWSER',
|
||||
value: config.browser,
|
||||
type: `string`,
|
||||
},
|
||||
{
|
||||
name: surroundInUnderscore('IS_CHROME'),
|
||||
name: 'CHROME',
|
||||
value: config.browser === 'chrome',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: surroundInUnderscore('IS_FIREFOX'),
|
||||
name: 'FIREFOX',
|
||||
value: config.browser === 'firefox',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: surroundInUnderscore('IS_SAFARI'),
|
||||
name: 'SAFARI',
|
||||
value: config.browser === 'safari',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: surroundInUnderscore('IS_EDGE'),
|
||||
name: 'EDGE',
|
||||
value: config.browser === 'edge',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: surroundInUnderscore('IS_OPERA'),
|
||||
name: 'OPERA',
|
||||
value: config.browser === 'opera',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: surroundInUnderscore('COMMAND'),
|
||||
name: 'COMMAND',
|
||||
value: config.command,
|
||||
type: `"build" | "serve"`,
|
||||
},
|
||||
@@ -50,17 +50,9 @@ export function getGlobals(
|
||||
export function getEntrypointGlobals(entrypointName: string) {
|
||||
return [
|
||||
{
|
||||
name: surroundInUnderscore('ENTRYPOINT'),
|
||||
name: 'ENTRYPOINT',
|
||||
value: entrypointName,
|
||||
type: `string`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't hardcode the complete name so that the string litterals in this file aren't replaced during
|
||||
* tests (which causes syntax errors), only during builds.
|
||||
*/
|
||||
function surroundInUnderscore(name: string): string {
|
||||
return `__${name}__`;
|
||||
}
|
||||
|
||||
@@ -232,7 +232,8 @@ export const fakeInternalConfig = fakeObjectCreator<InternalConfig>(() => {
|
||||
},
|
||||
zip: {
|
||||
artifactTemplate: '{{name}}-{{version}}.zip',
|
||||
ignoredSources: [],
|
||||
includeSources: [],
|
||||
excludeSources: [],
|
||||
sourcesRoot: fakeDir(),
|
||||
sourcesTemplate: '{{name}}-sources.zip',
|
||||
name: faker.person.firstName().toLowerCase(),
|
||||
|
||||
+8
-3
@@ -62,10 +62,15 @@ export async function zip(config?: InlineConfig): Promise<string[]> {
|
||||
saveTo: sourcesZipPath,
|
||||
filter(path) {
|
||||
const relativePath = relative(internalConfig.zip.sourcesRoot, path);
|
||||
const matchedPattern = internalConfig.zip.ignoredSources.find(
|
||||
(pattern) => minimatch(relativePath, pattern),
|
||||
|
||||
return (
|
||||
internalConfig.zip.includeSources.some((pattern) =>
|
||||
minimatch(relativePath, pattern),
|
||||
) ||
|
||||
!internalConfig.zip.excludeSources.some((pattern) =>
|
||||
minimatch(relativePath, pattern),
|
||||
)
|
||||
);
|
||||
return matchedPattern == null;
|
||||
},
|
||||
});
|
||||
zipFiles.push(sourcesZipPath);
|
||||
|
||||
+11
-1
@@ -308,10 +308,20 @@ function createDriver(
|
||||
storageArea: 'local' | 'session' | 'sync' | 'managed',
|
||||
): WxtStorageDriver {
|
||||
const getStorageArea = () => {
|
||||
if (browser.storage == null)
|
||||
if (browser.runtime == null) {
|
||||
throw Error(
|
||||
[
|
||||
"'wxt/storage' must be loaded in a web extension environment",
|
||||
'\n - If thrown during a build, see https://github.com/wxt-dev/wxt/issues/371',
|
||||
" - If thrown during tests, mock 'wxt/browser' correctly. See https://wxt.dev/guide/testing.html\n",
|
||||
].join('\n'),
|
||||
);
|
||||
}
|
||||
if (browser.storage == null) {
|
||||
throw Error(
|
||||
"You must add the 'storage' permission to your manifest to use 'wxt/storage'",
|
||||
);
|
||||
}
|
||||
|
||||
return browser.storage[storageArea];
|
||||
};
|
||||
|
||||
+15
-2
@@ -143,9 +143,22 @@ export interface InlineConfig {
|
||||
* @default config.root
|
||||
*/
|
||||
sourcesRoot?: string;
|
||||
/**
|
||||
* [Minimatch](https://www.npmjs.com/package/minimatch) patterns of files to include when
|
||||
* creating a ZIP of all your source code for Firefox. Patterns are relative to your
|
||||
* `config.zip.sourcesRoot`.
|
||||
*
|
||||
* This setting overrides `excludeSources`. So if a file matches both lists, it is included in the ZIP.
|
||||
*
|
||||
* @example
|
||||
* [
|
||||
* "coverage", // Ignore the coverage directory in the `sourcesRoot`
|
||||
* ]
|
||||
*/
|
||||
includeSources?: string[];
|
||||
/**
|
||||
* [Minimatch](https://www.npmjs.com/package/minimatch) patterns of files to exclude when
|
||||
* creating a ZIP of all your source code for Firfox. Patterns are relative to your
|
||||
* creating a ZIP of all your source code for Firefox. Patterns are relative to your
|
||||
* `config.zip.sourcesRoot`.
|
||||
*
|
||||
* Hidden files, node_modules, and tests are ignored by default.
|
||||
@@ -155,7 +168,7 @@ export interface InlineConfig {
|
||||
* "coverage", // Ignore the coverage directory in the `sourcesRoot`
|
||||
* ]
|
||||
*/
|
||||
ignoredSources?: string[];
|
||||
excludeSources?: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+7
-4
@@ -1,7 +1,10 @@
|
||||
// Globals defined by the vite-plugins/devServerGlobals.ts and utils/globals.ts
|
||||
declare const __COMMAND__: 'build' | 'serve';
|
||||
declare const __DEV_SERVER_PROTOCOL__: string;
|
||||
declare const __DEV_SERVER_HOSTNAME__: string;
|
||||
declare const __DEV_SERVER_PORT__: string;
|
||||
declare const __MANIFEST_VERSION__: 2 | 3;
|
||||
declare const __ENTRYPOINT__: string;
|
||||
|
||||
// Globals defined by the vite-plugins/devServerGlobals.ts and utils/globals.ts
|
||||
interface ImportMetaEnv {
|
||||
readonly COMMAND: 'build' | 'serve';
|
||||
readonly MANIFEST_VERSION: 2 | 3;
|
||||
readonly ENTRYPOINT: string;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ export interface InternalConfig {
|
||||
name?: string;
|
||||
artifactTemplate: string;
|
||||
sourcesTemplate: string;
|
||||
ignoredSources: string[];
|
||||
includeSources: string[];
|
||||
excludeSources: string[];
|
||||
sourcesRoot: string;
|
||||
};
|
||||
transformManifest: (manifest: Manifest.WebExtensionManifest) => void;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { browser } from 'wxt/browser';
|
||||
import { keepServiceWorkerAlive } from './utils/keep-service-worker-alive';
|
||||
import { reloadContentScript } from './utils/reload-content-scripts';
|
||||
|
||||
if (__COMMAND__ === 'serve') {
|
||||
if (import.meta.env.COMMAND === 'serve') {
|
||||
try {
|
||||
const ws = setupWebSocket((message) => {
|
||||
if (message.event === 'wxt:reload-extension') browser.runtime.reload();
|
||||
@@ -13,7 +13,7 @@ if (__COMMAND__ === 'serve') {
|
||||
reloadContentScript(message.data);
|
||||
});
|
||||
|
||||
if (__MANIFEST_VERSION__ === 3) {
|
||||
if (import.meta.env.MANIFEST_VERSION === 3) {
|
||||
// Tell the server the background script is loaded and ready to go
|
||||
ws.addEventListener('open', () => {
|
||||
const msg = { type: 'custom', event: 'wxt:background-initialized' };
|
||||
|
||||
@@ -5,12 +5,12 @@ import { ContentScriptContext } from 'wxt/client';
|
||||
(async () => {
|
||||
try {
|
||||
const { main, ...options } = definition;
|
||||
const ctx = new ContentScriptContext(__ENTRYPOINT__, options);
|
||||
const ctx = new ContentScriptContext(import.meta.env.ENTRYPOINT, options);
|
||||
|
||||
await main(ctx);
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
`The content script "${__ENTRYPOINT__}" crashed on startup!`,
|
||||
`The content script "${import.meta.env.ENTRYPOINT}" crashed on startup!`,
|
||||
err,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { logger } from '../sandbox/utils/logger';
|
||||
await main();
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
`The content script "${__ENTRYPOINT__}" crashed on startup!`,
|
||||
`The content script "${import.meta.env.ENTRYPOINT}" crashed on startup!`,
|
||||
err,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { setupWebSocket } from './utils/setup-web-socket';
|
||||
|
||||
if (__COMMAND__ === 'serve') {
|
||||
if (import.meta.env.COMMAND === 'serve') {
|
||||
try {
|
||||
setupWebSocket((message) => {
|
||||
if (message.event === 'wxt:reload-page') {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { logger } from '../sandbox/utils/logger';
|
||||
await definition.main();
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
`The unlisted script "${__ENTRYPOINT__}" crashed on startup!`,
|
||||
`The unlisted script "${import.meta.env.ENTRYPOINT}" crashed on startup!`,
|
||||
err,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user