Compare commits
635 Commits
v0.5.3
...
wxt-v0.18.10
| Author | SHA1 | Date | |
|---|---|---|---|
| 06a8c5fb0e | |||
| eb86413f35 | |||
| b29d49cbf1 | |||
| c0a0edb30c | |||
| b15a933c75 | |||
| 1851be22a7 | |||
| 39f6c29e4f | |||
| 936e89fbfb | |||
| ad365ecde4 | |||
| b4283e37bd | |||
| b467ad760a | |||
| 9fc6408ef9 | |||
| 394cb1a520 | |||
| ffec88549b | |||
| 4758bea187 | |||
| 6671471f75 | |||
| ae78dc7fb3 | |||
| b62af3d007 | |||
| 43ae44ecd5 | |||
| 5bab9d2f59 | |||
| 7edf1c8103 | |||
| 53b4eac955 | |||
| f9a10c2c52 | |||
| 8206ca9164 | |||
| 1a823cc008 | |||
| efc011eb81 | |||
| 35f6d28977 | |||
| 43fcbec0eb | |||
| a0d56b4d27 | |||
| 38ccb6ace6 | |||
| aaf75f1de1 | |||
| 21e8ca0a2c | |||
| 55444858bc | |||
| 771ea03069 | |||
| 38b71d1350 | |||
| cb781aceb5 | |||
| d53c792218 | |||
| 907f4d3672 | |||
| 8432d73a6b | |||
| 94a5435089 | |||
| edf3cf3f17 | |||
| 48783baec3 | |||
| c70f047696 | |||
| e6e0c713bc | |||
| 3691554a73 | |||
| 1a3436606b | |||
| 2c9e7750ec | |||
| fa67910007 | |||
| c77773eb20 | |||
| 148f3d53a6 | |||
| c7af789173 | |||
| 274d39b9a4 | |||
| d1edb2da0e | |||
| ed860027ef | |||
| 488fa6e773 | |||
| ea51cc04a9 | |||
| 6d1761533f | |||
| e35b540a3b | |||
| 7080b36173 | |||
| 4437dc404b | |||
| b3ddab7bcb | |||
| eb3b9bc334 | |||
| 34ea23030b | |||
| a25721708f | |||
| 6427e74edb | |||
| 15395a8c46 | |||
| 454b076eaf | |||
| 00597f6790 | |||
| ca29feaecf | |||
| f6420e5fdf | |||
| 78e0646043 | |||
| c15e75e6ab | |||
| 863a006ee7 | |||
| 9fd54cfa73 | |||
| 3535fb77fa | |||
| be22fc43cb | |||
| 3fd09edd25 | |||
| d36007b453 | |||
| 9eda887fd8 | |||
| b79220dbd1 | |||
| 927d29535f | |||
| 12805e9862 | |||
| d889a21465 | |||
| 8125d74057 | |||
| c39087a81a | |||
| 7b849b80cb | |||
| b98a5c378e | |||
| 215def7e15 | |||
| 3b954cc6fb | |||
| 20bdd8ad2f | |||
| cb9a9c0530 | |||
| 48d8d236c0 | |||
| 87d9511b31 | |||
| 5d8efef02f | |||
| c9008cd835 | |||
| 203a9cc234 | |||
| 5fcaf7c68b | |||
| c74e530d4a | |||
| 3f78be0c95 | |||
| 2a3d52045d | |||
| ea5b81d25e | |||
| cec9d7103a | |||
| 34dd2c1487 | |||
| a5667f85d0 | |||
| ec3dd52f83 | |||
| 87ebde3abb | |||
| dc5b55bffb | |||
| df20993917 | |||
| caa0fb31e6 | |||
| 95da4fb054 | |||
| a917f32a0e | |||
| 6ca376749c | |||
| 792e3032b9 | |||
| 38a5a2c440 | |||
| 21106ce188 | |||
| ec7263e7de | |||
| e7c3fc2a5e | |||
| f808cb7526 | |||
| c4795e7479 | |||
| b44a96ab81 | |||
| 3bfdc5c755 | |||
| acb75543ff | |||
| 25b45b9c09 | |||
| efd5c40043 | |||
| e47519fb76 | |||
| 171e32c272 | |||
| 54e5ed0bb4 | |||
| a94d673f31 | |||
| b7f7222c26 | |||
| aa5a9d4fa9 | |||
| 77da2d6ade | |||
| 3119c04e10 | |||
| c09994263e | |||
| 2a4fa9ae5c | |||
| c833d3b15b | |||
| d6e095bfce | |||
| 825160a3cc | |||
| e29ca33f82 | |||
| ca5a52c6f1 | |||
| 982c69f8ae | |||
| 6fc7d9254a | |||
| 2e0e104d48 | |||
| 02430fd7b8 | |||
| 2e6d35d193 | |||
| 7cf412ac1f | |||
| 9398cbb596 | |||
| ca9b96142e | |||
| db57c8e079 | |||
| 7e37e11caf | |||
| bb90029c54 | |||
| d3b14afbce | |||
| ba2197a609 | |||
| 4c558d3eb6 | |||
| dcd175444a | |||
| 16fc58404a | |||
| 28c7e7d9ed | |||
| 5a3b42a4b0 | |||
| c9c5d721ec | |||
| 1556b9ad73 | |||
| ca15b1f321 | |||
| 448436cb08 | |||
| c9ddc3d0f2 | |||
| 6b72f883b6 | |||
| cd3446bd7f | |||
| 829b371bba | |||
| 36b399dd49 | |||
| 08f32aa685 | |||
| 05db264e02 | |||
| de5a01834c | |||
| 1d260dbacb | |||
| 53c63b4556 | |||
| 816878bc15 | |||
| e087a0d6ef | |||
| 56b71491a6 | |||
| 121b521157 | |||
| 16c2e3218b | |||
| d9cba55d34 | |||
| 832cd5d640 | |||
| bb95e08d71 | |||
| 35269dad9e | |||
| 64d1498460 | |||
| 0d540a6df9 | |||
| b47c150daa | |||
| 38345481df | |||
| da92449e0f | |||
| 23b3980645 | |||
| 81b4b629c9 | |||
| 4f7e9cb050 | |||
| b226d9b947 | |||
| aabba41e86 | |||
| f19e6908b0 | |||
| 5f651cc3fe | |||
| 8a6acbaaf2 | |||
| 13ab8e4d01 | |||
| bd039dcbab | |||
| 9cd4e8342b | |||
| c9633cefec | |||
| 1dd1370ed7 | |||
| 9ff90d0acf | |||
| b754435589 | |||
| 195d2cceaf | |||
| 420d78b638 | |||
| b35e499355 | |||
| 41c3d6d015 | |||
| 64610bad41 | |||
| 45b7d7c67f | |||
| 0bb2746869 | |||
| f9b0aa45f8 | |||
| 6f6ce33bbd | |||
| e1c6020997 | |||
| 012bd7e67f | |||
| 35778f70cb | |||
| cb4f9aa752 | |||
| f80fb42483 | |||
| 02c79ca244 | |||
| 50e8c86ce9 | |||
| 6fbfc15be7 | |||
| c793d3cf6b | |||
| b5f4d8cc1b | |||
| 77e6d1f5a4 | |||
| 3f149ac4fa | |||
| c0dbffaa82 | |||
| 707f03a3eb | |||
| 8372462041 | |||
| 3fbbe2ccde | |||
| e7880fcde0 | |||
| ee5e76e4b1 | |||
| 1ae8d6bc46 | |||
| de7dd09f60 | |||
| 1649785826 | |||
| 91fc41cb15 | |||
| 9c80ad832b | |||
| 86b7162d99 | |||
| b8f8acd33d | |||
| d8905d23a4 | |||
| 5d2d124e5a | |||
| 4fda203def | |||
| 905bfc7a38 | |||
| 7c6973f0e6 | |||
| 969e39c541 | |||
| b256939cc4 | |||
| c46137644b | |||
| 1bd7ef56c4 | |||
| c258b99cec | |||
| d3abb32cb4 | |||
| 223ede9ff9 | |||
| 9d31a4eba1 | |||
| ea0e40c269 | |||
| bc24ea45a4 | |||
| 86d0c9b397 | |||
| c275ccf0da | |||
| 447a48f306 | |||
| 70b5cbc8db | |||
| 3459de0375 | |||
| c6817479bd | |||
| f02aae21f6 | |||
| 87a62a1791 | |||
| a0d1643021 | |||
| 856a946fa7 | |||
| 9d97164c20 | |||
| 6d526e7043 | |||
| 946072fc5a | |||
| 6b8dfdf02d | |||
| ba85fdf470 | |||
| 295f8601e3 | |||
| a38ccd8624 | |||
| b2dcec2f8a | |||
| e8355029d9 | |||
| 2b374b98d2 | |||
| d14d76a0c8 | |||
| d0f1c7065c | |||
| 3edb66d76d | |||
| bba8cdace1 | |||
| 22f82a67ee | |||
| b32c60ca73 | |||
| c93620cba5 | |||
| dd05ed4d4c | |||
| 21636defda | |||
| bb022646e3 | |||
| 37ad2c7ceb | |||
| b992631e00 | |||
| 35a5cc6717 | |||
| 310b56fe5d | |||
| 148234382e | |||
| c1a97b77b0 | |||
| 557ccb4854 | |||
| 83e7e8aab9 | |||
| 7bf490c59d | |||
| 9670babdbb | |||
| 42dfc2d5cf | |||
| 1527f0e275 | |||
| 66bd957ee0 | |||
| 72e3c5baa2 | |||
| 9318346ab3 | |||
| 1d6aceab0a | |||
| c1b5a9d270 | |||
| f0b2a12724 | |||
| c45677ed48 | |||
| 7a3f075e21 | |||
| 1e12ce2a0d | |||
| eca30296a7 | |||
| 41fa320815 | |||
| 873c24fa50 | |||
| d92db5ba8f | |||
| 1a6fe33f97 | |||
| 2db4ea77a9 | |||
| ba5349ccaf | |||
| addb689de9 | |||
| 2af8d28b82 | |||
| ddbc66813e | |||
| 0c8fc013a8 | |||
| 26e30aaae9 | |||
| 6557dfe430 | |||
| 9cee9eefb4 | |||
| f9cd7aaf05 | |||
| 9049804413 | |||
| d027a496f5 | |||
| dd7abddb7c | |||
| 98d2792e02 | |||
| 39b76d3ec0 | |||
| bc29bfd434 | |||
| 5e60f37ec5 | |||
| 6f901b32eb | |||
| 927aca612e | |||
| 2dcdae91eb | |||
| eb758bdeb8 | |||
| 5acf51af9d | |||
| f9718a1b71 | |||
| cf7f23d4c3 | |||
| 62ecb6f41e | |||
| fc45c37f22 | |||
| 68874e607e | |||
| 35865adcb2 | |||
| 3b63a51475 | |||
| d32e59e38f | |||
| dab8efa140 | |||
| c298d8552b | |||
| 87267347f3 | |||
| 326e84b667 | |||
| 4b005b450e | |||
| 3bf40fc4ed | |||
| 9ace395e11 | |||
| 64f42064ae | |||
| a525d786f1 | |||
| 948ee810da | |||
| 8687b2980e | |||
| 6f0814bc97 | |||
| 148c0da51f | |||
| ba09f3e0f1 | |||
| 54e24652da | |||
| d6516142d2 | |||
| 460667e3c0 | |||
| 6ed61d0766 | |||
| 971daf2784 | |||
| 89d8ef9a50 | |||
| a329e24818 | |||
| 249cf63da8 | |||
| 70a496108a | |||
| 214889e052 | |||
| b6ab7a9567 | |||
| 1ceb9e2e80 | |||
| 15ea81514f | |||
| 21d4e6dede | |||
| 5343430c0f | |||
| 8c834835c4 | |||
| 9a2cc18f64 | |||
| 8683bd4b77 | |||
| dca52864bb | |||
| 0c5643f648 | |||
| b7cdf1597c | |||
| 2770974261 | |||
| ab6a34afb6 | |||
| b0eb7da9b4 | |||
| 4f649fc872 | |||
| 1af64aa02f | |||
| c35acff259 | |||
| 995d4f8080 | |||
| b7e2aa3d8f | |||
| e347f4529f | |||
| 3d9683418d | |||
| bdce363eed | |||
| e7775f291a | |||
| 59f6a28c65 | |||
| f7534464bc | |||
| 01445fb1da | |||
| 1360eb7c01 | |||
| c99a281169 | |||
| 76e63e24c0 | |||
| f5ba1173da | |||
| 12079e6ffc | |||
| ff6740d429 | |||
| e6657cb533 | |||
| 2ad099bf7e | |||
| 6421ab34a4 | |||
| 8919c4015a | |||
| 712f2ed4ac | |||
| d1b9e5ded6 | |||
| 86182044d1 | |||
| e1f181356c | |||
| 5f241cf407 | |||
| b4a2cf4cb2 | |||
| aea137a3a1 | |||
| ad0e8e4144 | |||
| 7fd5752ef1 | |||
| 1a8b7ff635 | |||
| fe3ca0fcbd | |||
| f49ee9f005 | |||
| 961440c0ac | |||
| 9b562b0ca8 | |||
| 7b2563b2dc | |||
| 63f507ecf5 | |||
| 0a88955394 | |||
| 291d25b675 | |||
| 6f902cc598 | |||
| fde488ac82 | |||
| 0873c24ad8 | |||
| 7c02497148 | |||
| 25441a3b97 | |||
| f1cf866fe1 | |||
| d92a126489 | |||
| bcb93afe4e | |||
| 21cf3642cb | |||
| 2ef28ec0c4 | |||
| 59094c9af3 | |||
| ba41691296 | |||
| 8786aa91b3 | |||
| 0623d10653 | |||
| 85174d4994 | |||
| 4e2dd5d618 | |||
| 1a39a0d153 | |||
| f922648dd7 | |||
| e6142e3608 | |||
| ed73451fd0 | |||
| 8a25a2f60f | |||
| 397e9a8b45 | |||
| 7cef7680de | |||
| 0c57375758 | |||
| 2c6af84165 | |||
| 58e1371701 | |||
| 0d8e7463b8 | |||
| 77eeacaf0f | |||
| e80c134150 | |||
| 03c8ab4d6f | |||
| df13b9705c | |||
| 762ba0080d | |||
| 317b1b6dcc | |||
| 93175a6477 | |||
| 60d6707b11 | |||
| 97cbda3dab | |||
| 1611c1dba6 | |||
| b59252284a | |||
| 742b99657a | |||
| e2997a43e0 | |||
| 21dead60fd | |||
| 3d1bc0a12c | |||
| 4b24bee1fb | |||
| 82ed821eb5 | |||
| 60625280c2 | |||
| 083792b5f0 | |||
| 3da3e07bda | |||
| 64d61eb3f1 | |||
| aa6009e476 | |||
| d2cb8f9416 | |||
| 046a4809d3 | |||
| 207b750d4e | |||
| 077fa9939e | |||
| 44d715a29e | |||
| 3ab9fe4ae3 | |||
| 91b28c2cb9 | |||
| d1b523061f | |||
| c69ea3967f | |||
| 41527a2200 | |||
| 281f28192d | |||
| 67ffa44f9c | |||
| 421c0e412d | |||
| d21ee08eb6 | |||
| 7fa150dfae | |||
| 7ba52b18fd | |||
| 66e5079b84 | |||
| f1e8084be8 | |||
| 609ae2ae37 | |||
| c81dfff37c | |||
| 9c27820add | |||
| 22f8e10918 | |||
| 96d41f8b7c | |||
| c4ce44e001 | |||
| 6641ffaeed | |||
| 450dc0975f | |||
| d343555f41 | |||
| 7993908c6c | |||
| 94e1dbce24 | |||
| d14215946a | |||
| 345406f02a | |||
| 6b689bab23 | |||
| fcdf0dcbe9 | |||
| bd35acdae1 | |||
| 21c35ee593 | |||
| 0f09cbee0e | |||
| 183bb02e29 | |||
| 0bf4ea0897 | |||
| cd4d00e23e | |||
| 5de18e5371 | |||
| af823418ee | |||
| 0b8d101c33 | |||
| b587849126 | |||
| 2a35ce0a1e | |||
| c390b70f76 | |||
| c9fd739128 | |||
| 0806c06042 | |||
| 5f74a544a4 | |||
| 121778894c | |||
| 102c72a03c | |||
| a0507866db | |||
| f3874da780 | |||
| cc5d24ec92 | |||
| 08760015da | |||
| 5368371020 | |||
| 08d62a437a | |||
| 37e2348d79 | |||
| 6a30dc46fa | |||
| b75c553e51 | |||
| a56face03d | |||
| 19756c61ce | |||
| 5f54b4de17 | |||
| ea8935c47c | |||
| e37f73880d | |||
| 2e24b9e18a | |||
| f8a0fb37a2 | |||
| dd26b99027 | |||
| d9e9b43f8d | |||
| d580083727 | |||
| 5a70d9e57d | |||
| 1b1af245bd | |||
| 874a531a62 | |||
| a3d409f250 | |||
| b6758ca9fa | |||
| 2672308946 | |||
| 7ac171ed3b | |||
| 6a93f20bb3 | |||
| 921af6a5a1 | |||
| 21ebeacd20 | |||
| 527600031f | |||
| 91a804c492 | |||
| 54f3785063 | |||
| 44e4bc5295 | |||
| f464d7d33f | |||
| d0672739f0 | |||
| 44464f914f | |||
| 8940c41bdb | |||
| 446f265b6c | |||
| 7a465684c0 | |||
| 0369316463 | |||
| 8b74291d18 | |||
| 739b738100 | |||
| 95442dd39b | |||
| 4f82645c08 | |||
| d200c376f8 | |||
| b58fb02016 | |||
| e1bab6c746 | |||
| d10c22fbd9 | |||
| da1f7f3ea5 | |||
| 2659272f8a | |||
| 868fd27804 | |||
| d9fdcb5b33 | |||
| 580793158f | |||
| f58d69dc5f | |||
| c9028dd335 | |||
| 6342f59c5e | |||
| 2d91898452 | |||
| 4acefd601c | |||
| 9a2e71b481 | |||
| 6e578f3156 | |||
| 474de83e28 | |||
| 65fcfc0064 | |||
| 2d4983e88b | |||
| 4150e42c05 | |||
| 8d7150653a | |||
| 61e57b7b7c | |||
| 83add72312 | |||
| 3c723d2c92 | |||
| 1eb35c7207 | |||
| 725ecf7c64 | |||
| 3847092df4 | |||
| 19b11c236f | |||
| 4b2012c489 | |||
| 0591050f31 | |||
| b15dc7fc11 | |||
| 89d15babc2 | |||
| c616125689 | |||
| e97071b7d7 | |||
| 1fa049c5a7 | |||
| b48cee9715 | |||
| 24e69fe1bf | |||
| 41e154992a | |||
| 55707932a9 | |||
| 08115a40ae | |||
| 96be879918 | |||
| 1fc4ada66d | |||
| d27f299641 | |||
| 7183114370 | |||
| 7bd940450f | |||
| cf5a7d1411 | |||
| 5482b2f934 | |||
| c4a6ff928d | |||
| 455e7f3765 | |||
| 25b6ab92f5 | |||
| 50f6289ac5 | |||
| a0e1b4741e | |||
| ab672e9dbd | |||
| 7b3ea52e02 | |||
| e0929a68ba | |||
| 4c430725a5 | |||
| 7d745f6ec7 | |||
| 10091d7769 | |||
| 2e142b3038 | |||
| 361bb2dcc8 | |||
| 26fca5c0a2 | |||
| 30a61f4384 | |||
| 8e0a189d77 | |||
| cae44c9732 | |||
| fba8f0d017 | |||
| 3f260ee777 | |||
| 1f6a931b02 | |||
| 07891d028b | |||
| 1f448d1bf0 | |||
| 7722986537 | |||
| 4b73168618 | |||
| 16cebc538f | |||
| e4aaba98ab | |||
| c190d8c44c | |||
| 5801f96f79 | |||
| 92039b855e | |||
| f145e00cc9 | |||
| 87e8df90f5 | |||
| 419fab8193 |
@@ -0,0 +1,8 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
informational: true
|
||||
patch:
|
||||
default:
|
||||
informational: true
|
||||
@@ -1,2 +1,5 @@
|
||||
* text=auto eol=lf
|
||||
pnpm-lock.yaml linguist-generated
|
||||
package-lock.json linguist-generated
|
||||
bun.lockb linguist-generated
|
||||
yarn.lock linguist-generated
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report an issue with WXT
|
||||
title: ''
|
||||
labels: triage
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
### Describe the bug
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
### To Reproduce
|
||||
|
||||
Upload a ZIP or share a link to a repo representing the minimal reproduction. **_If you don't upload a minimal reproduction, you bug report will be closed._**
|
||||
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
### Expected behavior
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
### Screenshots
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
### Environment
|
||||
|
||||
<!--- Run `npx envinfo --system --browsers --binaries --npmPackages wxt,vite` and paste the output below -->
|
||||
|
||||
```
|
||||
Paste output here
|
||||
```
|
||||
|
||||
### Additional context
|
||||
|
||||
Add any other context about the problem here, otherwise you can delete this section.
|
||||
@@ -0,0 +1,74 @@
|
||||
name: "\U0001F41E Bug report"
|
||||
description: Report an issue with WXT
|
||||
labels: [pending-triage]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
- type: textarea
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!
|
||||
placeholder: I am doing ... What I expect is ... What actually happening is ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction
|
||||
description: |
|
||||
Please provide a minimal reproduction. This can include:
|
||||
|
||||
- A PR with a failing test case
|
||||
- A link to a github repo
|
||||
- A ZIP you upload to this issue
|
||||
|
||||
A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is required ([Why?](https://antfu.me/posts/why-reproductions-are-required)). If a report is vague (e.g. just a generic error message) and has no reproduction or a partial reproduction, it will be closed immediately and labeled with as "needs-reproduction". Once a reproduction is provided, it will be re-opened.
|
||||
placeholder: Reproduction URL or attach a ZIP
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction-steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Please provide any reproduction steps that may need to be described. E.g. if it happens only when running the dev or build script make sure it's clear which one to use.
|
||||
placeholder: Run `npm install` followed by `npm run dev`
|
||||
- type: textarea
|
||||
id: system-info
|
||||
attributes:
|
||||
label: System Info
|
||||
description: Output of `npx envinfo --system --browsers --binaries --npmPackages wxt,vite`
|
||||
render: shell
|
||||
placeholder: System, Binaries, Browsers
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: package-manager
|
||||
attributes:
|
||||
label: Used Package Manager
|
||||
description: Select the used package manager
|
||||
options:
|
||||
- npm
|
||||
- yarn
|
||||
- pnpm
|
||||
- bun
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: checkboxes
|
||||
attributes:
|
||||
label: Validations
|
||||
description: Before submitting the issue, please make sure you do the following
|
||||
options:
|
||||
- label: Read the [Contributing Guidelines](https://github.com/wxt-dev/wxt/blob/main/CONTRIBUTING.md).
|
||||
required: true
|
||||
- label: Read the [docs](https://wxt.dev/guide/installation.html).
|
||||
required: true
|
||||
- label: Check that there isn't [already an issue](https://github.com/wxt-dev/wxt/issues) that reports the same bug to avoid creating a duplicate.
|
||||
required: true
|
||||
- label: Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/wxt-dev/wxt/discussions) or join our [Discord Chat Server](https://discord.gg/ZFsZqGery9).
|
||||
required: true
|
||||
- label: The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.
|
||||
required: true
|
||||
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discord Chat
|
||||
url: https://discord.gg/ZFsZqGery9
|
||||
about: Ask questions and discuss with other WXT users in real time.
|
||||
- name: Questions & Discussions
|
||||
url: https://github.com/wxt-dev/wxt/discussions
|
||||
about: Use GitHub discussions for message-board style questions and discussions.
|
||||
@@ -0,0 +1,15 @@
|
||||
name: Basic Setup
|
||||
description: Install PNPM, Node, and dependencies
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
- name: Setup NodeJS
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: pnpm
|
||||
- name: Install Dependencies
|
||||
shell: bash
|
||||
run: pnpm install
|
||||
@@ -9,3 +9,7 @@ updates:
|
||||
directory: '/' # Location of package manifests
|
||||
schedule:
|
||||
interval: 'monthly'
|
||||
- package-ecosystem: 'github-actions'
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: 'monthly'
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
name: Publish Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Docker Image Tag
|
||||
required: true
|
||||
default: latest
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: docker/login-action@v3
|
||||
with:
|
||||
registry: https://${{ secrets.DOCKER_REGISTRY_HOSTNAME }}
|
||||
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
|
||||
- run: pnpm docs:build
|
||||
- run: docker build docs/.vitepress -t ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
|
||||
- run: docker push ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
|
||||
- run: curl -X POST -i ${{ secrets.UPDATE_DOCS_WEBHOOK }}
|
||||
@@ -1,47 +1,50 @@
|
||||
name: Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
package:
|
||||
description: Package to release
|
||||
default: wxt
|
||||
type: choice
|
||||
options:
|
||||
- wxt
|
||||
- module-react
|
||||
- module-vue
|
||||
- module-svelte
|
||||
- module-solid
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
uses: './.github/workflows/validate.yml'
|
||||
secrets: inherit
|
||||
|
||||
publish:
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- validate
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Setup NodeJS
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Bump and Tag
|
||||
run: |
|
||||
git config user.email "github-actions@users.noreply.github.com"
|
||||
git config user.name "GitHub Actions"
|
||||
pnpx changelogen@latest --release
|
||||
pnpm tsx scripts/bump-package-version.ts ${{ inputs.package }}
|
||||
git push
|
||||
git push --tags
|
||||
|
||||
- name: NPM
|
||||
run: |
|
||||
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}" > ~/.npmrc
|
||||
pnpm build
|
||||
pnpm publish
|
||||
working-directory: packages/${{ inputs.package }}
|
||||
|
||||
- name: GitHub Release
|
||||
run: pnpx changelogen@latest gh release --token ${{ secrets.GITHUB_TOKEN }}
|
||||
run: pnpm tsx scripts/create-github-release.ts ${{ inputs.package }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Sync Releases
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
package:
|
||||
description: Package to sync
|
||||
default: wxt
|
||||
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: ./.github/actions/setup
|
||||
- run: pnpm tsx scripts/sync-releases.ts ${{ inputs.package }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
+63
-110
@@ -7,115 +7,68 @@ on:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
wxt:
|
||||
name: WXT
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Setup NodeJS
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Formatting
|
||||
run: pnpm format:check
|
||||
|
||||
- name: Type Check
|
||||
run: pnpm compile
|
||||
|
||||
- name: Build Demo
|
||||
run: |
|
||||
pnpm build:all:chrome-mv2
|
||||
pnpm build:all:chrome-mv3
|
||||
pnpm build:all:firefox-mv2
|
||||
pnpm build:all:firefox-mv3
|
||||
pnpm tsc --noEmit
|
||||
pnpm wxt zip
|
||||
working-directory: demo
|
||||
|
||||
- name: Tests
|
||||
run: pnpm test:coverage --reporter=default --reporter=hanging-process
|
||||
|
||||
project-templates:
|
||||
name: Project Templates
|
||||
checks:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Setup NodeJS
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build Local Tarball
|
||||
run: pnpm pack
|
||||
|
||||
- name: Validate Vanilla
|
||||
working-directory: templates/vanilla
|
||||
run: |
|
||||
npm i
|
||||
npm i -D ../../wxt-*.tgz
|
||||
npm ls vite
|
||||
npm run build
|
||||
npm run compile
|
||||
|
||||
- name: Validate Vue
|
||||
working-directory: templates/vue
|
||||
run: |
|
||||
npm i
|
||||
npm i -D ../../wxt-*.tgz
|
||||
npm ls vite
|
||||
npm run build
|
||||
npm run compile
|
||||
|
||||
- name: Validate React
|
||||
working-directory: templates/react
|
||||
run: |
|
||||
npm i
|
||||
npm i -D ../../wxt-*.tgz
|
||||
npm ls vite
|
||||
npm run build
|
||||
npm run compile
|
||||
|
||||
- name: Validate Svelte
|
||||
working-directory: templates/svelte
|
||||
run: |
|
||||
npm i
|
||||
npm i -D ../../wxt-*.tgz
|
||||
npm ls vite
|
||||
npm run build
|
||||
npm run check
|
||||
|
||||
- name: Validate Solid
|
||||
working-directory: templates/solid
|
||||
run: |
|
||||
npm i
|
||||
npm i -D ../../wxt-*.tgz
|
||||
npm ls vite
|
||||
npm run build
|
||||
npm run compile
|
||||
- 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 buildc all
|
||||
build-demo:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm build:all
|
||||
working-directory: packages/wxt-demo
|
||||
- run: pnpm wxt zip
|
||||
working-directory: packages/wxt-demo
|
||||
tests:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: oven-sh/setup-bun@v1
|
||||
- name: pnpm test:coverage
|
||||
run: pnpm test:coverage --reporter=default --reporter=hanging-process
|
||||
- uses: codecov/codecov-action@v4
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
windows-tests:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm test run
|
||||
template:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
template:
|
||||
- react
|
||||
- solid
|
||||
- svelte
|
||||
- vanilla
|
||||
- vue
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: pnpm pack
|
||||
working-directory: packages/wxt
|
||||
- run: npm i
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
- run: npm i -D ../../packages/wxt/wxt-*.tgz
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
- run: pnpm compile
|
||||
if: matrix.template != 'svelte'
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
- run: pnpm check
|
||||
if: matrix.template == 'svelte'
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
- run: pnpm build
|
||||
working-directory: templates/${{ matrix.template }}
|
||||
|
||||
+4
-1
@@ -17,4 +17,7 @@ web-ext.config.ts
|
||||
templates/*/pnpm-lock.yaml
|
||||
templates/*/yarn.lock
|
||||
templates/*/package-lock.json
|
||||
docs/config.md
|
||||
docs/api/reference
|
||||
stats.html
|
||||
.tool-versions
|
||||
.cache
|
||||
|
||||
@@ -5,8 +5,3 @@ dist
|
||||
docs/.vitepress/cache
|
||||
pnpm-lock.yaml
|
||||
CHANGELOG.md
|
||||
.gitattributes
|
||||
.gitignore
|
||||
.prettierignore
|
||||
*.png
|
||||
*.svg
|
||||
|
||||
-608
@@ -1,608 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## v0.5.3
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.5.2...v0.5.3)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Allow function for vite config ([4ec904e](https://github.com/wxt-dev/wxt/commit/4ec904e))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Refactor how config is resolved ([#118](https://github.com/wxt-dev/wxt/pull/118))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron <aaronklinker1@gmail.com>
|
||||
- Aaron Klinker <aaronklinker1@gmail.com>
|
||||
|
||||
## v0.5.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.5.1...v0.5.2)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Import client utils when getting entrypoint config ([#117](https://github.com/wxt-dev/wxt/pull/117))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron <aaronklinker1@gmail.com>
|
||||
|
||||
## v0.5.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.5.0...v0.5.1)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Allow disabling auto-imports ([#114](https://github.com/wxt-dev/wxt/pull/114))
|
||||
- Include/exclude entrypoints based on target browser ([#115](https://github.com/wxt-dev/wxt/pull/115))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Allow any string for target browser ([b4de93d](https://github.com/wxt-dev/wxt/commit/b4de93d))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron <aaronklinker1@gmail.com>
|
||||
- Aaron Klinker <aaronklinker1@gmail.com>
|
||||
|
||||
## v0.5.0
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.4.1...v0.5.0)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- **types:** Don't write to files if nothing changes ([#107](https://github.com/wxt-dev/wxt/pull/107))
|
||||
- ⚠️ Change default `publicDir` to `<srcDir>/public` ([5f15f9c](https://github.com/wxt-dev/wxt/commit/5f15f9c))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Add link to examples repo ([46a5036](https://github.com/wxt-dev/wxt/commit/46a5036))
|
||||
- Fix typos ([beafa6a](https://github.com/wxt-dev/wxt/commit/beafa6a))
|
||||
- Make README pretty ([b33b663](https://github.com/wxt-dev/wxt/commit/b33b663))
|
||||
- Add migration docs ([e2350fe](https://github.com/wxt-dev/wxt/commit/e2350fe))
|
||||
- Add vite customization docs ([fe966b6](https://github.com/wxt-dev/wxt/commit/fe966b6))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Move repo to wxt-dev org ([ac7cbfc](https://github.com/wxt-dev/wxt/commit/ac7cbfc))
|
||||
- **deps-dev:** Bump prettier from 3.0.1 to 3.0.3 ([#111](https://github.com/wxt-dev/wxt/pull/111))
|
||||
- **deps-dev:** Bump tsx from 3.12.7 to 3.12.8 ([#109](https://github.com/wxt-dev/wxt/pull/109))
|
||||
- **deps-dev:** Bump @types/node from 20.5.0 to 20.5.9 ([#110](https://github.com/wxt-dev/wxt/pull/110))
|
||||
- Add entrypoints debug log ([dbd84c8](https://github.com/wxt-dev/wxt/commit/dbd84c8))
|
||||
|
||||
#### ⚠️ Breaking Changes
|
||||
|
||||
- ⚠️ Change default `publicDir` to `<srcDir>/public` ([5f15f9c](https://github.com/wxt-dev/wxt/commit/5f15f9c))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.4.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.4.0...v0.4.1)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- **cli:** Add `wxt clean` command to delete generated files ([#106](https://github.com/wxt-dev/wxt/pull/106))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- **init:** Don't show `cd .` when initializing the current directory ([e086374](https://github.com/wxt-dev/wxt/commit/e086374))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.4.0
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.3.2...v0.4.0)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Add `--debug` flag for printing debug logs for all CLI commands ([#75](https://github.com/wxt-dev/wxt/pull/75))
|
||||
- Replace `web-ext` with `web-ext-run` ([#101](https://github.com/wxt-dev/wxt/pull/101))
|
||||
- Generate types for `browser.i18n.getMessage` ([#103](https://github.com/wxt-dev/wxt/pull/103))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Allow adding custom content scripts ([b428a62](https://github.com/wxt-dev/wxt/commit/b428a62))
|
||||
- Don't overwrite `wxt.config.ts` content scripts, append entrypoints to it ([5f5f1d9](https://github.com/wxt-dev/wxt/commit/5f5f1d9))
|
||||
- ⚠️ Use relative path aliases inside `.wxt/tsconfig.json` ([#102](https://github.com/wxt-dev/wxt/pull/102))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Add contribution guide ([#76](https://github.com/wxt-dev/wxt/pull/76))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Setup dependabot for upgrading dependencies ([d66293c](https://github.com/wxt-dev/wxt/commit/d66293c))
|
||||
- Update social preview ([e164bd5](https://github.com/wxt-dev/wxt/commit/e164bd5))
|
||||
- Setup bug and feature issue templates ([2bde917](https://github.com/wxt-dev/wxt/commit/2bde917))
|
||||
- Upgrade to prettier 3 ([#77](https://github.com/wxt-dev/wxt/pull/77))
|
||||
- **deps-dev:** Bump vitest from 0.32.4 to 0.34.1 ([#81](https://github.com/wxt-dev/wxt/pull/81))
|
||||
- **deps-dev:** Bump ora from 6.3.1 to 7.0.1 ([#79](https://github.com/wxt-dev/wxt/pull/79))
|
||||
- **deps-dev:** Bump @types/node from 20.4.5 to 20.5.0 ([#78](https://github.com/wxt-dev/wxt/pull/78))
|
||||
- **deps-dev:** Bump tsup from 7.1.0 to 7.2.0 ([#80](https://github.com/wxt-dev/wxt/pull/80))
|
||||
- **deps-dev:** Bump @vitest/coverage-v8 from 0.32.4 to 0.34.1 ([#84](https://github.com/wxt-dev/wxt/pull/84))
|
||||
- **deps-dev:** Bump vitepress from 1.0.0-beta.5 to 1.0.0-rc.4 ([#85](https://github.com/wxt-dev/wxt/pull/85))
|
||||
- **deps-dev:** Bump vitest-mock-extended from 1.1.4 to 1.2.0 ([#87](https://github.com/wxt-dev/wxt/pull/87))
|
||||
- **deps-dev:** Bump lint-staged from 13.3.0 to 14.0.0 ([#89](https://github.com/wxt-dev/wxt/pull/89))
|
||||
- Fix remote code E2E test ([83e62a1](https://github.com/wxt-dev/wxt/commit/83e62a1))
|
||||
- Fix failing demo build ([b58a15e](https://github.com/wxt-dev/wxt/commit/b58a15e))
|
||||
- **deps-dev:** Bump vitest-mock-extended from 1.2.0 to 1.2.1 ([#97](https://github.com/wxt-dev/wxt/pull/97))
|
||||
- **deps-dev:** Bump lint-staged from 14.0.0 to 14.0.1 ([#100](https://github.com/wxt-dev/wxt/pull/100))
|
||||
- **deps-dev:** Bump vitest from 0.34.1 to 0.34.3 ([#99](https://github.com/wxt-dev/wxt/pull/99))
|
||||
- Increase E2E test timeout because GitHub Actions Window runner is slow ([2a0842b](https://github.com/wxt-dev/wxt/commit/2a0842b))
|
||||
- **deps-dev:** Bump vitepress from 1.0.0-rc.4 to 1.0.0-rc.10 ([#96](https://github.com/wxt-dev/wxt/pull/96))
|
||||
- Fix test watcher restarting indefinetly ([2c7922c](https://github.com/wxt-dev/wxt/commit/2c7922c))
|
||||
- Remove explict icon config from templates ([93bfee0](https://github.com/wxt-dev/wxt/commit/93bfee0))
|
||||
- Use import aliases in Vue template ([#104](https://github.com/wxt-dev/wxt/pull/104))
|
||||
|
||||
#### ⚠️ Breaking Changes
|
||||
|
||||
- ⚠️ Use relative path aliases inside `.wxt/tsconfig.json` ([#102](https://github.com/wxt-dev/wxt/pull/102))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.3.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.3.1...v0.3.2)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Discover icons from the public directory ([#72](https://github.com/wxt-dev/wxt/pull/72))
|
||||
- Don't allow auto-importing from subdirectories ([d54d611](https://github.com/wxt-dev/wxt/commit/d54d611))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Document the `url:` import prefix for remote code ([323045a](https://github.com/wxt-dev/wxt/commit/323045a))
|
||||
- Fix typos ([97f0938](https://github.com/wxt-dev/wxt/commit/97f0938))
|
||||
- Fix capitalization ([39467d1](https://github.com/wxt-dev/wxt/commit/39467d1))
|
||||
- Generate markdown for config reference ([#74](https://github.com/wxt-dev/wxt/pull/74))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Upgrade dependencies ([798f02f](https://github.com/wxt-dev/wxt/commit/798f02f))
|
||||
- Upgrade vite (`v4.3` → `v4.4`) ([547c185](https://github.com/wxt-dev/wxt/commit/547c185))
|
||||
- Update templates to work with CSS entrypoints ([7f15305](https://github.com/wxt-dev/wxt/commit/7f15305))
|
||||
- Improve file list output in CI ([#73](https://github.com/wxt-dev/wxt/pull/73))
|
||||
|
||||
### 🤖 CI
|
||||
|
||||
- Validate templates against `main` ([#66](https://github.com/wxt-dev/wxt/pull/66))
|
||||
- List vite version when validating project templates ([ef140dc](https://github.com/wxt-dev/wxt/commit/ef140dc))
|
||||
- Validate templates using tarball to avoid version conflicts within the `wxt/node_modules` directory ([edfa075](https://github.com/wxt-dev/wxt/commit/edfa075))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.3.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.3.0...v0.3.1)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- CSS entrypoints ([#61](https://github.com/wxt-dev/wxt/pull/61))
|
||||
- `init` command for bootstrapping new projects ([#65](https://github.com/wxt-dev/wxt/pull/65))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Add zip command to installation scripts ([94a1097](https://github.com/wxt-dev/wxt/commit/94a1097))
|
||||
- Add output paths to entrypoint docs ([3a336eb](https://github.com/wxt-dev/wxt/commit/3a336eb))
|
||||
- Update installation docs ([aea866c](https://github.com/wxt-dev/wxt/commit/aea866c))
|
||||
- Add publishing docs ([4184b05](https://github.com/wxt-dev/wxt/commit/4184b05))
|
||||
- Add a section for extensions using WXT ([709b61a](https://github.com/wxt-dev/wxt/commit/709b61a))
|
||||
- Add a comparison page to compare and contrast against Plasmo ([38d4f9c](https://github.com/wxt-dev/wxt/commit/38d4f9c))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Update template projects to v0.3 ([#56](https://github.com/wxt-dev/wxt/pull/56))
|
||||
- Branding and logo ([#60](https://github.com/wxt-dev/wxt/pull/60))
|
||||
- Simplify binary setup ([#62](https://github.com/wxt-dev/wxt/pull/62))
|
||||
- Add Solid template ([#63](https://github.com/wxt-dev/wxt/pull/63))
|
||||
- Increate E2E test timeout to fix flakey test ([dfe424f](https://github.com/wxt-dev/wxt/commit/dfe424f))
|
||||
|
||||
### 🤖 CI
|
||||
|
||||
- Speed up demo validation ([3a9fd39](https://github.com/wxt-dev/wxt/commit/3a9fd39))
|
||||
- Fix flakey failure when validating templates ([25677ba](https://github.com/wxt-dev/wxt/commit/25677ba))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
- BeanWei ([@BeanWei](https://github.com/BeanWei))
|
||||
|
||||
## v0.3.0
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.5...v0.3.0)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- ⚠️ Add type safety to `browser.runtime.getURL` ([58a84ec](https://github.com/wxt-dev/wxt/commit/58a84ec))
|
||||
- ⚠️ Change default `publicDir` to `<rootDir>/public` ([19c0948](https://github.com/wxt-dev/wxt/commit/19c0948))
|
||||
- Windows support ([#50](https://github.com/wxt-dev/wxt/pull/50))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Add `WebWorker` lib to generated tsconfig ([2c70246](https://github.com/wxt-dev/wxt/commit/2c70246))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Update entrypoint directory links ([0aebb67](https://github.com/wxt-dev/wxt/commit/0aebb67))
|
||||
|
||||
### 🌊 Types
|
||||
|
||||
- Allow any string for the `__BROWSER__` global ([6092235](https://github.com/wxt-dev/wxt/commit/6092235))
|
||||
|
||||
### 🤖 CI
|
||||
|
||||
- Improve checks against `demo/` extension ([9cc464f](https://github.com/wxt-dev/wxt/commit/9cc464f))
|
||||
|
||||
#### ⚠️ Breaking Changes
|
||||
|
||||
- ⚠️ Add type safety to `browser.runtime.getURL` ([58a84ec](https://github.com/wxt-dev/wxt/commit/58a84ec))
|
||||
- ⚠️ Change default `publicDir` to `<rootDir>/public` ([19c0948](https://github.com/wxt-dev/wxt/commit/19c0948))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.2.5
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.4...v0.2.5)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Auto-import from subdirectories ([547fee0](https://github.com/wxt-dev/wxt/commit/547fee0))
|
||||
- Include background script in dev mode if user doesn't define one ([ca20a21](https://github.com/wxt-dev/wxt/commit/ca20a21))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Don't crash when generating types in dev mode ([d8c1903](https://github.com/wxt-dev/wxt/commit/d8c1903))
|
||||
- Properly load entrypoints that reference `import.meta` ([54b18cc](https://github.com/wxt-dev/wxt/commit/54b18cc))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Update templates to wxt@0.2 ([9d00eb2](https://github.com/wxt-dev/wxt/commit/9d00eb2))
|
||||
|
||||
### 🤖 CI
|
||||
|
||||
- Validate project templates ([9ac756f](https://github.com/wxt-dev/wxt/commit/9ac756f))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.2.4
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.3...v0.2.4)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Add `wxt zip` command ([#47](https://github.com/wxt-dev/wxt/pull/47))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.2.3
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.2...v0.2.3)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Correctly lookup open port ([#45](https://github.com/wxt-dev/wxt/pull/45))
|
||||
- Read boolean maniest options from meta tags correctly ([495c5c8](https://github.com/wxt-dev/wxt/commit/495c5c8))
|
||||
- Some fields cannot be overridden from `config.manifest` ([#46](https://github.com/wxt-dev/wxt/pull/46))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.2.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.1...v0.2.2)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Register content scripts correctly in dev mode ([2fb5a54](https://github.com/wxt-dev/wxt/commit/2fb5a54))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.2.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.0...v0.2.1)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Support all content script options ([6f5bf89](https://github.com/wxt-dev/wxt/commit/6f5bf89))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Remove HMR log ([90fa6bf](https://github.com/wxt-dev/wxt/commit/90fa6bf))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.2.0
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.6...v0.2.0)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- ⚠️ Rename `defineBackgroundScript` to `defineBackground` ([5b48ae9](https://github.com/wxt-dev/wxt/commit/5b48ae9))
|
||||
- Recongize unnamed content scripts (`content.ts` and `content/index.ts`) ([3db5cec](https://github.com/wxt-dev/wxt/commit/3db5cec))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Update templates ([f28a29e](https://github.com/wxt-dev/wxt/commit/f28a29e))
|
||||
- Add docs for each type of entrypoint ([77cbfc1](https://github.com/wxt-dev/wxt/commit/77cbfc1))
|
||||
- Add inline JSDoc for public types ([375a2a6](https://github.com/wxt-dev/wxt/commit/375a2a6))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Run `wxt prepare` on `postinstall` ([c1ea9ba](https://github.com/wxt-dev/wxt/commit/c1ea9ba))
|
||||
- Don't format lockfile ([5c7e041](https://github.com/wxt-dev/wxt/commit/5c7e041))
|
||||
|
||||
#### ⚠️ Breaking Changes
|
||||
|
||||
- ⚠️ Rename `defineBackgroundScript` to `defineBackground` ([5b48ae9](https://github.com/wxt-dev/wxt/commit/5b48ae9))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.1.6
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.5...v0.1.6)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Resolve tsconfig paths in vite ([ea92a27](https://github.com/wxt-dev/wxt/commit/ea92a27))
|
||||
- Add logs when a hot reload happens ([977246f](https://github.com/wxt-dev/wxt/commit/977246f))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- React and Vue starter templates ([#33](https://github.com/wxt-dev/wxt/pull/33))
|
||||
- Svelte template ([#34](https://github.com/wxt-dev/wxt/pull/34))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.1.5
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.4...v0.1.5)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Include `vite/client` types ([371be99](https://github.com/wxt-dev/wxt/commit/371be99))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.1.4
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.3...v0.1.4)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Fix regression where manifest was not listed first in build summary ([fa2b656](https://github.com/wxt-dev/wxt/commit/fa2b656))
|
||||
- Fix config hook implementations for vite plugins ([49965e7](https://github.com/wxt-dev/wxt/commit/49965e7))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Update CLI screenshot ([0a26673](https://github.com/wxt-dev/wxt/commit/0a26673))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Update prettier ignore ([68611ae](https://github.com/wxt-dev/wxt/commit/68611ae))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.1.3
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.2...v0.1.3)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Add tsconfig path aliases ([#32](https://github.com/wxt-dev/wxt/pull/32))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Merge `manifest` option from both inline and user config ([05ca998](https://github.com/wxt-dev/wxt/commit/05ca998))
|
||||
- Cleanup build summary with sourcemaps ([ac0b28e](https://github.com/wxt-dev/wxt/commit/ac0b28e))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Create documentation site ([#31](https://github.com/wxt-dev/wxt/pull/31))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Upgrade to pnpm 8 ([0ce7c9d](https://github.com/wxt-dev/wxt/commit/0ce7c9d))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.1.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.1...v0.1.2)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Accept a function for `config.manifest` ([ee49837](https://github.com/wxt-dev/wxt/commit/ee49837))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Add missing types for `webextension-polyfill` and the `manifest` option ([636aa48](https://github.com/wxt-dev/wxt/commit/636aa48))
|
||||
- Only add imports to JS files ([b29c3c6](https://github.com/wxt-dev/wxt/commit/b29c3c6))
|
||||
- Generate valid type for `EntrypointPath` when there are no entrypoints ([6e7184d](https://github.com/wxt-dev/wxt/commit/6e7184d))
|
||||
|
||||
### 🌊 Types
|
||||
|
||||
- Change `config.vite` to `UserConfig` ([ef6001e](https://github.com/wxt-dev/wxt/commit/ef6001e))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.1.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.0...v0.1.1)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Allow dashes in entrypoint names ([2e51e73](https://github.com/wxt-dev/wxt/commit/2e51e73))
|
||||
- Unable to read entrypoint options ([#28](https://github.com/wxt-dev/wxt/pull/28))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.1.0
|
||||
|
||||
Initial release of WXT. Full support for production builds and initial toolkit for development:
|
||||
|
||||
- HMR support when HTML page dependencies change
|
||||
- Reload extension when background changes
|
||||
- Reload HTML pages when saving them directly
|
||||
- Re-register and reload tabs when content scripts change
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.0.2...v0.1.0)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Content scripts reloading ([#25](https://github.com/wxt-dev/wxt/pull/25))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Update feature list ([0255028](https://github.com/wxt-dev/wxt/commit/0255028))
|
||||
|
||||
### 🤖 CI
|
||||
|
||||
- Create github release ([b7c078f](https://github.com/wxt-dev/wxt/commit/b7c078f))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.0.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.0.1...v0.0.2)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Reload extension when source code is changed ([#17](https://github.com/wxt-dev/wxt/pull/17))
|
||||
- Setup background script web socket/reload ([#22](https://github.com/wxt-dev/wxt/pull/22))
|
||||
- Reload HTML files individually ([#23](https://github.com/wxt-dev/wxt/pull/23))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Output chunks to a chunks directory ([2dd7a99](https://github.com/wxt-dev/wxt/commit/2dd7a99))
|
||||
- Remove hash from content script css outputs ([#20](https://github.com/wxt-dev/wxt/pull/20))
|
||||
- Overwrite files with the same name when renaming entrypoints in dev mode ([37986bf](https://github.com/wxt-dev/wxt/commit/37986bf))
|
||||
- Separate template builds to prevent sharing chunks ([7f3a1e8](https://github.com/wxt-dev/wxt/commit/7f3a1e8))
|
||||
- Show Vite warnings and errors ([c51f0e0](https://github.com/wxt-dev/wxt/commit/c51f0e0))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Add milestone progress badge to README ([684197d](https://github.com/wxt-dev/wxt/commit/684197d))
|
||||
- Fix milestone link in README ([e14f81d](https://github.com/wxt-dev/wxt/commit/e14f81d))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Refactor build output type ([#19](https://github.com/wxt-dev/wxt/pull/19))
|
||||
- Refactor build outputs to support transpiled templates ([a78aada](https://github.com/wxt-dev/wxt/commit/a78aada))
|
||||
- Rename `templates` to `virtual-modules` ([#24](https://github.com/wxt-dev/wxt/pull/24))
|
||||
- Update cli screenshot ([54eb118](https://github.com/wxt-dev/wxt/commit/54eb118))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v0.0.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.0.0...v0.0.1)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Add logger to config ([232ff7a](https://github.com/wxt-dev/wxt/commit/232ff7a))
|
||||
- Export and bootstrap the `/client` package ([5b07c95](https://github.com/wxt-dev/wxt/commit/5b07c95))
|
||||
- Resolve entrypoints based on filesystem ([a63f061](https://github.com/wxt-dev/wxt/commit/a63f061))
|
||||
- Separate output directories for each browser/manifest version ([f09ffbb](https://github.com/wxt-dev/wxt/commit/f09ffbb))
|
||||
- Build entrypoints and output `manfiest.json` ([1e7c738](https://github.com/wxt-dev/wxt/commit/1e7c738))
|
||||
- Automatically add CSS files to content scripts ([047ce04](https://github.com/wxt-dev/wxt/commit/047ce04))
|
||||
- Download and bundle remote URL imports ([523c7df](https://github.com/wxt-dev/wxt/commit/523c7df))
|
||||
- Generate type declarations and config for project types and auto-imports ([21debad](https://github.com/wxt-dev/wxt/commit/21debad))
|
||||
- Good looking console output ([e2cc995](https://github.com/wxt-dev/wxt/commit/e2cc995))
|
||||
- Dev server working and a valid extension is built ([505e419](https://github.com/wxt-dev/wxt/commit/505e419))
|
||||
- Virtualized content script entrypoint ([ca29537](https://github.com/wxt-dev/wxt/commit/ca29537))
|
||||
- Provide custom, typed globals defined by Vite ([8c59a1c](https://github.com/wxt-dev/wxt/commit/8c59a1c))
|
||||
- Copy public directory to outputs ([1a25f2b](https://github.com/wxt-dev/wxt/commit/1a25f2b))
|
||||
- Support browser and chrome styles for mv2 popups ([7945c94](https://github.com/wxt-dev/wxt/commit/7945c94))
|
||||
- Support browser and chrome styles for mv2 popups ([7abb577](https://github.com/wxt-dev/wxt/commit/7abb577))
|
||||
- Support more CLI flags for `build` and `dev` ([#9](https://github.com/wxt-dev/wxt/pull/9))
|
||||
- Add more supported browser types ([f114c5b](https://github.com/wxt-dev/wxt/commit/f114c5b))
|
||||
- Open browser when starting dev server ([#11](https://github.com/wxt-dev/wxt/pull/11))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Support `srcDir` config ([739d19f](https://github.com/wxt-dev/wxt/commit/739d19f))
|
||||
- Root path customization now works ([4faa3b3](https://github.com/wxt-dev/wxt/commit/4faa3b3))
|
||||
- Print durations as ms/s based on total time ([3e37de9](https://github.com/wxt-dev/wxt/commit/3e37de9))
|
||||
- Don't print error twice when background crashes ([407627c](https://github.com/wxt-dev/wxt/commit/407627c))
|
||||
- Load package.json from root not cwd ([3ca16ee](https://github.com/wxt-dev/wxt/commit/3ca16ee))
|
||||
- Only allow a single entrypoint with a given name ([8eb4e86](https://github.com/wxt-dev/wxt/commit/8eb4e86))
|
||||
- Respect the mv2 popup type ([0f37ceb](https://github.com/wxt-dev/wxt/commit/0f37ceb))
|
||||
- Respect background type and persistent manifest options ([573ef80](https://github.com/wxt-dev/wxt/commit/573ef80))
|
||||
- Make content script array orders consistent ([f380378](https://github.com/wxt-dev/wxt/commit/f380378))
|
||||
- Firefox manifest warnings in dev mode ([50bb845](https://github.com/wxt-dev/wxt/commit/50bb845))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Update README ([785ea54](https://github.com/wxt-dev/wxt/commit/785ea54))
|
||||
- Update README ([99ccadb](https://github.com/wxt-dev/wxt/commit/99ccadb))
|
||||
- Update description ([07a262e](https://github.com/wxt-dev/wxt/commit/07a262e))
|
||||
- Update README ([58a0ef4](https://github.com/wxt-dev/wxt/commit/58a0ef4))
|
||||
- Update README ([23ed6f7](https://github.com/wxt-dev/wxt/commit/23ed6f7))
|
||||
- Add initial release milestone link to README ([b400e54](https://github.com/wxt-dev/wxt/commit/b400e54))
|
||||
- Fix typo in README ([5590c9d](https://github.com/wxt-dev/wxt/commit/5590c9d))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Refactor cli files into their own directory ([e6c0d84](https://github.com/wxt-dev/wxt/commit/e6c0d84))
|
||||
- Simplify `BuildOutput` type ([1f6c4a0](https://github.com/wxt-dev/wxt/commit/1f6c4a0))
|
||||
- Move `.exvite` directory into `srcDir` instead of `root` ([53fb805](https://github.com/wxt-dev/wxt/commit/53fb805))
|
||||
- Refactor CLI commands ([b8952b6](https://github.com/wxt-dev/wxt/commit/b8952b6))
|
||||
- Improve build summary sorting ([ec57e8c](https://github.com/wxt-dev/wxt/commit/ec57e8c))
|
||||
- Remove comments ([e3e9c0d](https://github.com/wxt-dev/wxt/commit/e3e9c0d))
|
||||
- Refactor internal config creation ([7c634f4](https://github.com/wxt-dev/wxt/commit/7c634f4))
|
||||
- Check virtual entrypoints feature in README ([70208f4](https://github.com/wxt-dev/wxt/commit/70208f4))
|
||||
- Add E2E tests and convert to vitest workspace ([5813302](https://github.com/wxt-dev/wxt/commit/5813302))
|
||||
- Rename package to wxt ([51a1072](https://github.com/wxt-dev/wxt/commit/51a1072))
|
||||
- Fix header log's timestamp ([8ca5657](https://github.com/wxt-dev/wxt/commit/8ca5657))
|
||||
- Fix demo global usage ([1ecfedd](https://github.com/wxt-dev/wxt/commit/1ecfedd))
|
||||
- Refactor folder structure ([9ab3953](https://github.com/wxt-dev/wxt/commit/9ab3953))
|
||||
- Fix release workflow ([2e94f2a](https://github.com/wxt-dev/wxt/commit/2e94f2a))
|
||||
|
||||
### 🤖 CI
|
||||
|
||||
- Create validation workflow ([#12](https://github.com/wxt-dev/wxt/pull/12))
|
||||
- Create release workflow ([#13](https://github.com/wxt-dev/wxt/pull/13))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron Klinker ([@aklinker1](https://github.com/aklinker1))
|
||||
+63
-4
@@ -37,13 +37,13 @@ pnpm build
|
||||
|
||||
```sh
|
||||
# Build WXT package, then build demo extension
|
||||
cd demo
|
||||
cd packages/wxt-demo
|
||||
pnpm build
|
||||
```
|
||||
|
||||
```sh
|
||||
# Build WXT package, then start the demo extension in dev mode
|
||||
cd demo
|
||||
cd packages/wxt-demo
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -67,6 +75,57 @@ To run tests for a specific file, add the filename at the end of the test comman
|
||||
pnpm test manifest-contents
|
||||
```
|
||||
|
||||
Unit and E2E tests are ran together via [Vitest workspaces](https://vitest.dev/guide/#workspaces-support).
|
||||
All test (unit and E2E) for all packages are ran together via [Vitest workspaces](https://vitest.dev/guide/#workspaces-support).
|
||||
|
||||
If you want to manually test a change, you can modify the demo project for your test, but please don't leave those changes committed once you open a PR.
|
||||
|
||||
## Templates
|
||||
|
||||
Each directory inside `templates/` is it's own standalone project. Simply `cd` into the directory you're updating, install dependencies with `npm` (NOT `pnpm`), and run the relevant commands
|
||||
|
||||
```sh
|
||||
cd templates/vue
|
||||
npm i
|
||||
npm run dev
|
||||
npm run build
|
||||
```
|
||||
|
||||
Note that templates are hardcoded to a specific version of `wxt` from NPM, they do not use the local version. PR checks will test your PR's changes against the templates, but if you want to manually do it, update the package.json dependency:
|
||||
|
||||
```diff
|
||||
"devDependencies": {
|
||||
"typescript": "^5.3.2",
|
||||
"vite-plugin-solid": "^2.7.0",
|
||||
- "wxt": "^0.8.0"
|
||||
+ "wxt": "../.."
|
||||
}
|
||||
```
|
||||
|
||||
Then run `npm i` again.
|
||||
|
||||
### Adding Templates
|
||||
|
||||
To add a template, copy the vanilla template and give it a new name.
|
||||
|
||||
```sh
|
||||
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).
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
<span>WXT</span>
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/wxt" target="_blank"><img alt="npm" src="https://img.shields.io/npm/v/wxt?labelColor=black&color=%234fa048"></a>
|
||||
<span> </span>
|
||||
<a href="https://www.npmjs.com/package/wxt" target="_blank"><img alt="npm" src="https://img.shields.io/npm/dm/wxt?labelColor=black&color=%234fa048"></a>
|
||||
<span> </span>
|
||||
<a href="https://github.com/wxt-dev/wxt/blob/main/LICENSE" target="_blank"><img alt="NPM" src="https://img.shields.io/npm/l/wxt?labelColor=black&color=%234fa048"></a>
|
||||
<span> </span>
|
||||
<a href="https://codecov.io/github/wxt-dev/wxt" target="_blank"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/wxt-dev/wxt?labelColor=black&color=%234fa048"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<span>Next-gen framework for developing web extensions.</span>
|
||||
<br/>
|
||||
@@ -14,24 +24,30 @@
|
||||
<p align="center">
|
||||
<a href="https://wxt.dev" target="_blank">Get Started</a>
|
||||
•
|
||||
<a href="https://wxt.dev/get-started/installation.html" target="_blank">Installation</a>
|
||||
<a href="https://wxt.dev/guide/installation.html" target="_blank">Installation</a>
|
||||
•
|
||||
<a href="https://wxt.dev/guide/background.html" target="_blank">Entrypoints</a>
|
||||
<a href="https://wxt.dev/api/config.html" target="_blank">Configuration</a>
|
||||
•
|
||||
<a href="https://wxt.dev/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>
|
||||
|
||||

|
||||
|
||||
## Demo
|
||||
|
||||
https://github.com/wxt-dev/wxt/assets/10101283/4d678939-1bdb-495c-9c36-3aa281d84c94
|
||||
|
||||
## Quick Start
|
||||
|
||||
Bootstrap a new project:
|
||||
|
||||
```sh
|
||||
pnpx wxt@latest init <project-name>
|
||||
pnpm dlx wxt@latest init <project-name>
|
||||
```
|
||||
|
||||
Or see the [installation guide](https://wxt.dev/get-started/installation.html) to get started with WXT.
|
||||
Or see the [installation guide](https://wxt.dev/guide/installation.html) to get started with WXT.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -41,14 +57,11 @@ Or see the [installation guide](https://wxt.dev/get-started/installation.html) t
|
||||
- 📂 File based entrypoints
|
||||
- 🚔 TypeScript
|
||||
- 🦾 Auto-imports
|
||||
- ⬇️ Download and bundle remote URL imports
|
||||
- 🤖 Automated publishing
|
||||
- 🎨 Frontend framework agnostic: works with Vue, React, Svelte, etc
|
||||
- 🖍️ Quickly bootstrap a new project
|
||||
|
||||
### Coming Soon
|
||||
|
||||
- 📏 Bundle analysis
|
||||
- 🤖 Automated publishing
|
||||
- ⬇️ Download and bundle remote URL imports
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
require('../dist/cli.cjs');
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"name": "WXT Demo",
|
||||
"version": "1.0.0",
|
||||
"description": "Demo extension for WXT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "pnpm -w build && wxt",
|
||||
"build": "pnpm -w build && wxt build",
|
||||
"build:all": "pnpm -w build && 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",
|
||||
"zip": "pnpm -w build && wxt zip",
|
||||
"compile": "pnpm -w build && tsc --noEmit",
|
||||
"postinstall": "pnpm -w build && wxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"webextension-polyfill": "^0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/webextension-polyfill": "^0.10.0",
|
||||
"sass": "^1.64.0",
|
||||
"wxt": "workspace:*"
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
export default defineBackground(() => {
|
||||
console.log(browser.runtime.id);
|
||||
logId();
|
||||
console.log({
|
||||
browser: __BROWSER__,
|
||||
chrome: __IS_CHROME__,
|
||||
firefox: __IS_FIREFOX__,
|
||||
manifestVersion: __MANIFEST_VERSION__,
|
||||
});
|
||||
|
||||
// @ts-expect-error: should only accept entrypoints or public assets
|
||||
browser.runtime.getURL('/');
|
||||
browser.runtime.getURL('/background.js');
|
||||
browser.runtime.getURL('/icon/128.png');
|
||||
|
||||
// @ts-expect-error: should only accept known message names
|
||||
browser.i18n.getMessage('test');
|
||||
browser.i18n.getMessage('prompt_for_name');
|
||||
browser.i18n.getMessage('hello', 'Aaron');
|
||||
browser.i18n.getMessage('bye', ['Aaron']);
|
||||
browser.i18n.getMessage('@@extension_id');
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
import '../../common/style.css';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['*://*/*'],
|
||||
async main() {
|
||||
console.log(browser.runtime.id);
|
||||
logId();
|
||||
mountContentScriptUi();
|
||||
},
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": ["../tsconfig.base.json", "./.wxt/tsconfig.json"]
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
srcDir: 'src',
|
||||
manifest: {
|
||||
default_locale: 'en',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,116 @@
|
||||
# Development
|
||||
|
||||
WXT's main goal is providing the best DX it possibly can. When running your extension in dev mode, each part of your extension is reloaded separately when possible.
|
||||
|
||||
| | HMR | Reloaded individually | Reload extension | Restart browser |
|
||||
| ------------------- | :-: | :-------------------: | :--------------: | :----------------------------------------------------: |
|
||||
| HTML File | | ✅ |
|
||||
| HTML Dependency | ✅ |
|
||||
| MV3 Content Script | | ✅ |
|
||||
| MV2 Content Script | | | ✅ |
|
||||
| Background | | | ✅ |
|
||||
| manifest.json | | | | 🟡 See [#16](https://github.com/wxt-dev/wxt/issues/16) |
|
||||
| `wxt.config.ts` | | | | 🟡 See [#10](https://github.com/wxt-dev/wxt/issues/10) |
|
||||
| `web-ext.config.ts` | | | | 🟡 See [#10](https://github.com/wxt-dev/wxt/issues/10) |
|
||||
|
||||
## Dev Mode vs Production Builds
|
||||
|
||||
There are some notable differences between the development and production versions of an extension. During development:
|
||||
|
||||
1. **Content scripts are not listed in the `manifest.json`** when targeting MV3. Instead, the [`scripting`](https://developer.chrome.com/docs/extensions/reference/api/scripting) permission is used to register content scripts at runtime so they can be reloaded individually.
|
||||
|
||||
To get the list of content scripts during development, run the following in the background's console:
|
||||
|
||||
```ts
|
||||
await chrome.scripting.getRegisteredContentScripts();
|
||||
```
|
||||
|
||||
2. **The CSP is modified to allow loading scripts from the dev server**. Make sure you're using Chrome v110 or above for HMR to work.
|
||||
|
||||
3. If you don't include a background script/service worker, one will be created to perform various tasks in dev mode, mostly related to reloading different parts of the extension on change.
|
||||
|
||||
For production builds, none of the above modifications will be applied, and you're extension/manifest will only include what you have defined.
|
||||
|
||||
## Configure Browser Startup
|
||||
|
||||
WXT uses [`web-ext` by Mozilla](https://github.com/mozilla/web-ext) to automatically open a browser with the extension installed. You can configure the runner's behavior via the [`runner`](/api/reference/wxt/interfaces/InlineConfig#runner) option, or in a separate gitignored file, `web-ext.config.ts`.
|
||||
|
||||
:::code-group
|
||||
|
||||
```ts [wxt.config.ts]
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
runner: {
|
||||
// Runner config
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```ts [web-ext.config.ts]
|
||||
import { defineRunnerConfig } from 'wxt';
|
||||
|
||||
export default defineRunnerConfig({
|
||||
// Runner config
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Browser Binaries
|
||||
|
||||
`web-ext`'s browser discovery is very limited. By default, it only guesses at where Chrome and Firefox are installed. If you've customized your install locations, you may need to tell `web-ext` where the binaries/executables are located using the [`binaries` option](/api/reference/wxt/interfaces/ExtensionRunnerConfig#binaries). For other Chromium based browsers, like Edge or Opera, you'll need to explicitly list them in the `binaries` option as well, otherwise they will open in Chrome by default.
|
||||
|
||||
```ts
|
||||
// ~/web-ext.config.ts
|
||||
import { defineRunnerConfig } from 'wxt';
|
||||
|
||||
export default defineRunnerConfig({
|
||||
binaries: {
|
||||
chrome: '/path/to/chrome-beta', // Use Chrome Beta instead of regular Chrome
|
||||
firefox: 'firefoxdeveloperedition', // Use Firefox Developer Edition instead of regular Firefox
|
||||
edge: '/path/to/edge', // Open MS Edge when running "wxt -b edge"
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::tip
|
||||
When configuring browser binaries, it's helpful to put them in `~/web-ext.config.ts` instead of the project directory's `web-ext.config.ts` file. When placed in your home directory (`~/`), this config will be used by all WXT projects, so you only need to configure the binaries once.
|
||||
:::
|
||||
|
||||
### Other options
|
||||
|
||||
You can customize other options as well, like startup URLs, profiles, or additional command line arguments:
|
||||
|
||||
```ts
|
||||
// web-ext.config.ts
|
||||
import { defineRunnerConfig } from 'wxt';
|
||||
|
||||
export default defineRunnerConfig({
|
||||
startUrls: ['https://google.com', 'https://duckduckgo.com'],
|
||||
chromiumProfile: '/path/to/profile/to/use',
|
||||
chromiumArgs: ['--window-size=400,300'],
|
||||
});
|
||||
```
|
||||
|
||||
For a full list of options, see the [API Reference](/api/reference/wxt/interfaces/ExtensionRunnerConfig).
|
||||
|
||||
## Reload the Extension
|
||||
|
||||
Normally, to manually reload an extension, you have to visit `chrome://extensions` and click the reload button for your extension.
|
||||
|
||||
When running `wxt` command to start the dev server, WXT adds a keyboard shortcut `Alt+R`, that reloads the extension when pressed, without visiting `chrome://extensions`. This can also be customized or disabled:
|
||||
|
||||
```ts [wxt.config.ts]
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
dev: {
|
||||
reloadCommand: 'Alt+T', // false, to disable
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::info
|
||||
This shortcut is only available during development, and is not be added to your extension when running `wxt build` or `wxt-zip`.
|
||||
:::
|
||||
@@ -0,0 +1,2 @@
|
||||
FROM lipanski/docker-static-website:latest
|
||||
COPY dist .
|
||||
@@ -0,0 +1,34 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
tag?: string;
|
||||
}>();
|
||||
|
||||
const examples = ref();
|
||||
onMounted(async () => {
|
||||
const res = await fetch(
|
||||
'https://raw.githubusercontent.com/wxt-dev/wxt-examples/main/examples.json',
|
||||
);
|
||||
examples.value = await res.json();
|
||||
});
|
||||
|
||||
const filteredExamples = computed(() => {
|
||||
if (props.tag == null) return examples.value;
|
||||
|
||||
return examples.value.filter((example) => {
|
||||
return example.tags?.includes(props.tag);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ul>
|
||||
<li v-if="examples == null">Loading...</li>
|
||||
<template v-else>
|
||||
<li v-for="example of filteredExamples">
|
||||
<a :href="example.url" target="_blank">{{ example.name }}</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</template>
|
||||
@@ -1,109 +1,198 @@
|
||||
<script lang="ts" setup>
|
||||
const extensions = [
|
||||
{
|
||||
name: 'GitHub: Better Line Counts',
|
||||
description: 'Remove generated files from GitHub line counts.',
|
||||
icon: 'https://lh3.googleusercontent.com/GcffNyCJaxT2G9dsQCJHhUEMlu_E0vEzph5cLPrQj7UHKat7QyCzGu69Dmp_DDUL8rY-bPMFJceQarS1wcqdwTalTg=s256',
|
||||
link: 'https://chrome.google.com/webstore/detail/github-better-line-counts/ocfdgncpifmegplaglcnglhioflaimkd',
|
||||
},
|
||||
import { computed } from 'vue';
|
||||
import useListExtensionDetails, {
|
||||
ChromeExtension,
|
||||
} from '../composables/useListExtensionDetails';
|
||||
|
||||
// Add extension IDs here. Order doesn't matter, will be sorted by weekly active users
|
||||
// During the transition from chrome.google.com/webstore to
|
||||
// chromewebstore.google.com, queue.wxt.dev might return null for your
|
||||
// extension. If it does, use "<slug>/<id>" instead of just the ID. The slug
|
||||
// can be retrieved from the URL of the item on chromewebstore.google.com
|
||||
const chromeExtensionIds = [
|
||||
'ocfdgncpifmegplaglcnglhioflaimkd', // GitHub: Better Line Counts
|
||||
'mgmdkjcljneegjfajchedjpdhbadklcf', // Anime Skip Player
|
||||
'bfbnagnphiehemkdgmmficmjfddgfhpl', // UltraWideo
|
||||
'elfaihghhjjoknimpccccmkioofjjfkf', // StayFree - Website Blocker & Web Analytics
|
||||
'okifoaikfmpfcamplcfjkpdnhfodpkil', // Doozy: Ai Made Easy
|
||||
'lknmjhcajhfbbglglccadlfdjbaiifig', // tl;dv - Record, Transcribe & ChatGPT for Google Meet
|
||||
'youtube中文配音/oglffgiaiekgeicdgkdlnlkhliajdlja', // Youtube中文配音
|
||||
'agjnjboanicjcpenljmaaigopkgdnihi', // PreMiD
|
||||
'aiakblgmlabokilgljkglggnpflljdgp', // Markdown Sticky Notes
|
||||
'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,
|
||||
'oajalfneblkfiejoadecnmodfpnaeblh', // MS Edge TTS (Text to Speech)
|
||||
'nedcanggplmbbgmlpcjiafgjcpdimpea', // YTBlock - Block any content from YouTube™
|
||||
'oadbjpccljkplmhnjekgjamejnbadlne', // demo.fun - Interactive product demos that convert
|
||||
'iopdafdcollfgaoffingmahpffckmjni', // SmartEReply: Elevate Your LinkedIn™ Engagement with AI 🚀📈
|
||||
'khjdmjcmpolknpccmaaipmidphjokhdf', // WorkFlowy MultiFlow
|
||||
];
|
||||
|
||||
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
|
||||
const sortedExtensions = computed(() => {
|
||||
if (!data.value?.length) return [];
|
||||
|
||||
return [...data.value]
|
||||
.filter((item) => item != null)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
// Sort based on the user count weighted by the rating
|
||||
sortKey: ((item.rating ?? 5) / 5) * item.weeklyActiveUsers,
|
||||
}))
|
||||
.filter((item) => !!item)
|
||||
.sort((l, r) => r.sortKey - l.sortKey);
|
||||
});
|
||||
|
||||
function getStoreUrl(extension: ChromeExtension) {
|
||||
const url = new URL(extension.storeUrl);
|
||||
url.searchParams.set('utm_source', 'wxt.dev');
|
||||
return url.href;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="vp-doc">
|
||||
<div class="container">
|
||||
<h2>Who's Using WXT?</h2>
|
||||
<ul>
|
||||
<li v-for="extension of extensions">
|
||||
<img :src="extension.icon" :alt="`${extension.name} icon`" />
|
||||
<a :href="extension.link" target="_blank">{{ extension.name }}</a>
|
||||
<small>{{ extension.description }}</small>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Open a PR to add your extension to the list!</p>
|
||||
</div>
|
||||
</section>
|
||||
<p v-if="isLoading" style="text-align: center; opacity: 50%">Loading...</p>
|
||||
<p
|
||||
v-else-if="err || sortedExtensions.length === 0"
|
||||
style="text-align: center; opacity: 50%"
|
||||
>
|
||||
Failed to load extension details.
|
||||
</p>
|
||||
<ul v-else>
|
||||
<li
|
||||
v-for="extension of sortedExtensions"
|
||||
:key="extension.id"
|
||||
class="relative"
|
||||
>
|
||||
<img
|
||||
:src="extension.iconUrl"
|
||||
:alt="`${extension.name} icon`"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<div class="relative">
|
||||
<a
|
||||
:href="getStoreUrl(extension)"
|
||||
target="_blank"
|
||||
:title="extension.name"
|
||||
class="extension-name"
|
||||
>{{ extension.name }}</a
|
||||
>
|
||||
<p class="description" :title="extension.shortDescription">
|
||||
{{ extension.shortDescription }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="user-count">
|
||||
<span>{{ extension.weeklyActiveUsers.toLocaleString() }} users</span
|
||||
><template v-if="extension.rating != null"
|
||||
>,
|
||||
<span>{{ extension.rating }} stars</span>
|
||||
</template>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="centered pr">
|
||||
<a
|
||||
href="https://github.com/wxt-dev/wxt/edit/main/docs/.vitepress/components/UsingWxtSection.vue"
|
||||
target="_blank"
|
||||
>Open a PR</a
|
||||
>
|
||||
to add your extension to the list!
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.vp-doc {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.vp-doc {
|
||||
padding: 0 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.vp-doc {
|
||||
padding: 0 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
margin-bottom: 16px;
|
||||
li img {
|
||||
width: 116px;
|
||||
height: 116px;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--vp-c-default-soft);
|
||||
}
|
||||
|
||||
ul {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
align-items: stretch;
|
||||
gap: 16px;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
margin: 16px 0;
|
||||
padding: 0;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
ul {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
ul {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0 !important;
|
||||
padding: 12px;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 12px;
|
||||
flex: 1;
|
||||
}
|
||||
a,
|
||||
small {
|
||||
text-align: center;
|
||||
}
|
||||
small {
|
||||
opacity: 50%;
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
p {
|
||||
.centered {
|
||||
text-align: center;
|
||||
opacity: 50%;
|
||||
}
|
||||
a {
|
||||
color: var(--vp-c-text-1);
|
||||
|
||||
li a,
|
||||
li .user-count,
|
||||
li .description {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
li .user-count {
|
||||
opacity: 70%;
|
||||
font-size: small;
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
li a {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
li div {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
li .description {
|
||||
opacity: 90%;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
li .extension-name {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.pr {
|
||||
opacity: 70%;
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
export interface ChromeExtension {
|
||||
id: string;
|
||||
name: string;
|
||||
iconUrl: string;
|
||||
weeklyActiveUsers: number;
|
||||
shortDescription: string;
|
||||
storeUrl: string;
|
||||
rating: number | undefined;
|
||||
}
|
||||
|
||||
const operationName = 'WxtDocsUsedBy';
|
||||
const query = `query ${operationName}($ids:[String!]!) {
|
||||
chromeExtensions(ids: $ids) {
|
||||
id
|
||||
name
|
||||
iconUrl
|
||||
weeklyActiveUsers
|
||||
shortDescription
|
||||
storeUrl
|
||||
rating
|
||||
}
|
||||
}`;
|
||||
|
||||
export default function (ids: string[]) {
|
||||
const data = ref<ChromeExtension[]>();
|
||||
const err = ref<unknown>();
|
||||
const isLoading = ref(true);
|
||||
|
||||
fetch('https://queue.wxt.dev/api', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
operationName,
|
||||
query,
|
||||
variables: { ids },
|
||||
}),
|
||||
})
|
||||
.then(async (res) => {
|
||||
isLoading.value = false;
|
||||
const {
|
||||
data: { chromeExtensions },
|
||||
} = await res.json();
|
||||
data.value = chromeExtensions;
|
||||
err.value = undefined;
|
||||
})
|
||||
.catch((error) => {
|
||||
isLoading.value = false;
|
||||
console.error(error);
|
||||
data.value = undefined;
|
||||
err.value = error;
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
err,
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
+138
-56
@@ -1,82 +1,164 @@
|
||||
import { defineConfig } from 'vitepress';
|
||||
import { generateConfigDocs } from './plugins/generate-config-docs';
|
||||
import typedocSidebar from '../api/reference/typedoc-sidebar.json';
|
||||
import {
|
||||
menuGroup,
|
||||
menuItem,
|
||||
menuRoot,
|
||||
navItem,
|
||||
prepareTypedocSidebar,
|
||||
} from './utils/menus';
|
||||
import { meta, script } from './utils/head';
|
||||
|
||||
const title = 'Next-gen Web Extension Framework';
|
||||
const titleSuffix = ' – WXT';
|
||||
const description =
|
||||
"WXT provides the best developer experience, making it quick, easy, and fun to develop chrome extensions for all browsers. With built-in utilities for building, zipping, and publishing your extension, it's easy to get started.";
|
||||
const ogTitle = `${title}${titleSuffix}`;
|
||||
const ogUrl = 'https://wxt.dev';
|
||||
const ogImage = 'https://wxt.dev/social-preview.png';
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
titleTemplate: `:title${titleSuffix}`,
|
||||
title: 'WXT',
|
||||
description,
|
||||
vite: {
|
||||
clearScreen: false,
|
||||
plugins: [generateConfigDocs()],
|
||||
},
|
||||
description: 'Next gen framework for developing web extensions',
|
||||
lastUpdated: true,
|
||||
sitemap: {
|
||||
hostname: 'https://wxt.dev',
|
||||
},
|
||||
|
||||
head: [
|
||||
meta('og:type', 'website'),
|
||||
meta('og:title', ogTitle),
|
||||
meta('og:image', ogImage),
|
||||
meta('og:url', ogUrl),
|
||||
meta('og:description', description),
|
||||
meta('twitter:card', 'summary_large_image', { useName: true }),
|
||||
script('https://umami.aklinker1.io/script.js', {
|
||||
'data-website-id': 'c1840c18-a12c-4a45-a848-55ae85ef7915',
|
||||
async: '',
|
||||
}),
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
logo: '/logo.svg',
|
||||
logo: {
|
||||
src: '/logo.svg',
|
||||
alt: 'WXT logo',
|
||||
},
|
||||
|
||||
editLink: {
|
||||
pattern: 'https://github.com/wxt-dev/wxt/edit/main/docs/:path',
|
||||
},
|
||||
|
||||
search: {
|
||||
provider: 'local',
|
||||
},
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'discord', link: 'https://discord.gg/ZFsZqGery9' },
|
||||
{ icon: 'github', link: 'https://github.com/wxt-dev/wxt' },
|
||||
],
|
||||
|
||||
nav: [
|
||||
{ text: 'Get Started', link: '/get-started/installation.md' },
|
||||
{ text: 'Guide', link: '/guide/auto-imports.md' },
|
||||
{ text: 'Config', link: '/config.md' },
|
||||
{ text: 'API', link: '/api.md' },
|
||||
navItem('Get Started', '/get-started/introduction'),
|
||||
navItem('Guide', '/guide/key-concepts/manifest'),
|
||||
navItem('API', '/api/reference/wxt'),
|
||||
navItem('Examples', '/examples'),
|
||||
],
|
||||
|
||||
sidebar: {
|
||||
'/get-started/': [
|
||||
{
|
||||
text: 'Get Started',
|
||||
items: [
|
||||
{ text: 'Introduction', link: '/get-started/introduction.md' },
|
||||
{ text: 'Installation', link: '/get-started/installation.md' },
|
||||
{ text: 'Configuration', link: '/get-started/configuration.md' },
|
||||
{ text: 'Entrypoints', link: '/get-started/entrypoints.md' },
|
||||
{ text: 'Assets', link: '/get-started/assets.md' },
|
||||
{ text: 'Build Targets', link: '/get-started/build-targets.md' },
|
||||
{ text: 'Publishing', link: '/get-started/publishing.md' },
|
||||
{ text: 'Testing', link: '/get-started/testing.md' },
|
||||
{ text: 'Compare', link: '/get-started/compare.md' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/guide/': [
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
{ text: 'Auto-imports', link: '/guide/auto-imports.md' },
|
||||
{ text: 'Manifest.json', link: '/guide/manifest.md' },
|
||||
{ text: 'Extension APIs', link: '/guide/extension-apis.md' },
|
||||
{ text: 'Remote Code', link: '/guide/remote-code.md' },
|
||||
{ text: 'Vite', link: '/guide/vite.md' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Entrypoints',
|
||||
items: [
|
||||
{ text: 'Background', link: '/guide/background.md' },
|
||||
{ text: 'Bookmarks', link: '/guide/bookmarks.md' },
|
||||
{ text: 'Content Scripts', link: '/guide/content-scripts.md' },
|
||||
{ text: 'CSS', link: '/guide/css.md' },
|
||||
{ text: 'Devtools', link: '/guide/devtools.md' },
|
||||
{ text: 'History', link: '/guide/history.md' },
|
||||
{ text: 'Newtab', link: '/guide/newtab.md' },
|
||||
{ text: 'Options', link: '/guide/options.md' },
|
||||
{ text: 'Popup', link: '/guide/popup.md' },
|
||||
{ text: 'Sandbox', link: '/guide/sandbox.md' },
|
||||
{ text: 'Sidepanel', link: '/guide/sidepanel.md' },
|
||||
{ text: 'Unlisted Pages', link: '/guide/unlisted-pages.md' },
|
||||
{ text: 'Unlisted Scripts', link: '/guide/unlisted-scripts.md' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
'/get-started/': menuRoot([
|
||||
menuGroup('Get Started', '/get-started/', [
|
||||
menuItem('Introduction', 'introduction'),
|
||||
menuItem('Installation', 'installation'),
|
||||
menuItem('Configuration', 'configuration'),
|
||||
menuItem('Entrypoints', 'entrypoints'),
|
||||
menuItem('Assets', 'assets'),
|
||||
menuItem('Testing', 'testing'),
|
||||
menuItem('Publishing', 'publishing'),
|
||||
menuItem('Migrate to WXT', 'migrate-to-wxt'),
|
||||
menuItem('Compare', 'compare'),
|
||||
]),
|
||||
]),
|
||||
'/guide/': menuRoot([
|
||||
menuGroup('Key Concepts', '/guide/key-concepts/', [
|
||||
menuItem('Manifest', 'manifest'),
|
||||
menuItem('Auto-imports', 'auto-imports'),
|
||||
menuItem('Web Extension Polyfill', 'web-extension-polyfill'),
|
||||
menuItem('Frontend Frameworks', 'frontend-frameworks'),
|
||||
menuItem('Content Script UI', 'content-script-ui'),
|
||||
]),
|
||||
menuGroup('Directory Structure', '/guide/directory-structure/', [
|
||||
// Folders
|
||||
menuItem('.output/', 'output'),
|
||||
menuItem('.wxt/', 'wxt'),
|
||||
menuItem('assets/', 'assets'),
|
||||
menuItem('components/', 'components'),
|
||||
menuItem('composables/', 'composables'),
|
||||
menuGroup('entrypoints/', '/guide/directory-structure/entrypoints/', [
|
||||
menuItem('background', 'background.md'),
|
||||
menuItem('bookmarks', 'bookmarks.md'),
|
||||
menuItem('*.content.ts', 'content-scripts.md'),
|
||||
menuItem('*.css', 'css.md'),
|
||||
menuItem('devtools', 'devtools.md'),
|
||||
menuItem('history', 'history.md'),
|
||||
menuItem('newtab', 'newtab.md'),
|
||||
menuItem('options', 'options.md'),
|
||||
menuItem('popup', 'popup.md'),
|
||||
menuItem('sandbox', 'sandbox.md'),
|
||||
menuItem('sidepanel', 'sidepanel.md'),
|
||||
menuItem('*.html', 'unlisted-pages.md'),
|
||||
menuItem('*.ts', 'unlisted-scripts.md'),
|
||||
]),
|
||||
menuItem('hooks/', 'hooks'),
|
||||
menuItem('public/', 'public/', [
|
||||
menuItem('_locales/', 'public/locales'),
|
||||
]),
|
||||
menuItem('utils/', 'utils'),
|
||||
|
||||
socialLinks: [{ icon: 'github', link: 'https://github.com/wxt-dev/wxt' }],
|
||||
// Files
|
||||
menuItem('.env', 'env'),
|
||||
menuItem('package.json', 'package'),
|
||||
menuItem('tsconfig.json', 'tsconfig'),
|
||||
menuItem('web-ext.config.ts', 'web-ext-config'),
|
||||
menuItem('wxt.config.ts', 'wxt-config'),
|
||||
]),
|
||||
menuGroup('Extension APIs', '/guide/extension-apis/', [
|
||||
menuItem('Storage', 'storage'),
|
||||
menuItem('Messaging', 'messaging'),
|
||||
menuItem('Scripting', 'scripting'),
|
||||
menuItem('Others', 'others'),
|
||||
]),
|
||||
menuGroup('Go Further', '/guide/go-further/', [
|
||||
menuItem('Testing', 'testing'),
|
||||
menuItem('ES Modules', 'es-modules'),
|
||||
menuItem('Debugging', 'debugging'),
|
||||
menuItem('Handling Updates', 'handling-updates'),
|
||||
menuItem('Vite', 'vite'),
|
||||
menuItem('Custom Events', 'custom-events'),
|
||||
menuItem('Reusable Modules', 'reusable-modules'),
|
||||
menuItem('Remote Code', 'remote-code'),
|
||||
menuItem('Entrypoint Side Effects', 'entrypoint-side-effects'),
|
||||
menuItem('How WXT Works', 'how-wxt-works'),
|
||||
]),
|
||||
]),
|
||||
'/api/': menuRoot([
|
||||
menuGroup('CLI', '/api/cli/', [
|
||||
menuItem('wxt', 'wxt.md'),
|
||||
menuItem('wxt build', 'wxt-build.md'),
|
||||
menuItem('wxt zip', 'wxt-zip.md'),
|
||||
menuItem('wxt prepare', 'wxt-prepare.md'),
|
||||
menuItem('wxt clean', 'wxt-clean.md'),
|
||||
menuItem('wxt init', 'wxt-init.md'),
|
||||
menuItem('wxt submit', 'wxt-submit.md'),
|
||||
menuItem('wxt submit init', 'wxt-submit-init.md'),
|
||||
]),
|
||||
menuGroup('API Reference', prepareTypedocSidebar(typedocSidebar)),
|
||||
]),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { resolve, join } from 'node:path';
|
||||
import consola from 'consola';
|
||||
import { execaCommand } from 'execa';
|
||||
|
||||
const cliDir = resolve('packages/wxt/src/cli/commands');
|
||||
const cliDirGlob = resolve(cliDir, '**');
|
||||
|
||||
export default {
|
||||
watch: [cliDirGlob],
|
||||
async load() {
|
||||
consola.info(`Generating CLI docs`);
|
||||
|
||||
const [wxt, build, zip, prepare, clean, init, submit, submitInit] =
|
||||
await Promise.all([
|
||||
getWxtHelp(''),
|
||||
getWxtHelp('build'),
|
||||
getWxtHelp('zip'),
|
||||
getWxtHelp('prepare'),
|
||||
getWxtHelp('clean'),
|
||||
getWxtHelp('init'),
|
||||
getPublishExtensionHelp(''),
|
||||
getPublishExtensionHelp('init'),
|
||||
]);
|
||||
|
||||
consola.success(`Generated CLI docs`);
|
||||
return {
|
||||
wxt,
|
||||
build,
|
||||
zip,
|
||||
prepare,
|
||||
clean,
|
||||
init,
|
||||
submit,
|
||||
submitInit,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
async function getHelp(command: string): Promise<string> {
|
||||
const res = await execaCommand(command + ' --help', {
|
||||
cwd: 'packages/wxt',
|
||||
});
|
||||
return res.stdout;
|
||||
}
|
||||
|
||||
function getWxtHelp(command: string): Promise<string> {
|
||||
return getHelp(`pnpm -s wxt ${command}`.trim());
|
||||
}
|
||||
|
||||
async function getPublishExtensionHelp(command: string): Promise<string> {
|
||||
const res = await getHelp(
|
||||
`./node_modules/.bin/publish-extension ${command}`.trim(),
|
||||
);
|
||||
return res.replace(/\$ publish-extension/g, '$ wxt submit');
|
||||
}
|
||||
|
||||
export interface Command {
|
||||
name: string;
|
||||
docs: string;
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
import { resolve } from 'node:path';
|
||||
import { Project, ts, Type, Node, JSDocableNode } from 'ts-morph';
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { format } from 'prettier';
|
||||
import consola from 'consola';
|
||||
|
||||
let hasGenerated = false;
|
||||
|
||||
const externalTypesPath = resolve('src/core/types/external.ts');
|
||||
const configTemplatePath = resolve('docs/config.tpl.md');
|
||||
const configPath = resolve('docs/config.md');
|
||||
|
||||
const PREFACE = `<!--
|
||||
DO NOT EDIT
|
||||
Generated by \`wxt/docs/.vitepress/plugins/generate-config-docs.ts\`
|
||||
To make changes to the config reference, update the JSDoc in \`src/core/types/external.ts\`.
|
||||
-->`;
|
||||
|
||||
/**
|
||||
* Custom property paths that should not be recursively inspected. Usually 3rd party types.
|
||||
*/
|
||||
const LEAF_PATHS = ['imports', 'vite', 'server'];
|
||||
|
||||
/**
|
||||
* Override any types that resolve to `import(...)` instead of their type names when calling
|
||||
* `type.getText()`.
|
||||
*
|
||||
* This also stops any further type inspection for objects, meaning the object will be documented,
|
||||
* not it's properties.
|
||||
*/
|
||||
const CUSTOM_TYPES = {
|
||||
manifest:
|
||||
'Manifest | Promise<Manifest> | () => Manifest | () => Promise<Manifest>',
|
||||
imports: "false | Partial<import('unimport').UnimportOptions>",
|
||||
vite: "Omit<import('vite').UserConfig, 'root' | 'configFile' | 'mode'>",
|
||||
};
|
||||
|
||||
export function generateConfigDocs() {
|
||||
writeFileSync(configPath, '');
|
||||
|
||||
const generateDocs = async () => {
|
||||
consola.info('Generating /config.md');
|
||||
try {
|
||||
const project = new Project({
|
||||
tsConfigFilePath: resolve('tsconfig.json'),
|
||||
});
|
||||
|
||||
// Load file containing "UserConfig"
|
||||
const externalTypesFile = project.addSourceFileAtPath(externalTypesPath);
|
||||
project.resolveSourceFileDependencies();
|
||||
|
||||
const inlineConfigInterface =
|
||||
externalTypesFile.getInterfaceOrThrow('InlineConfig');
|
||||
|
||||
const getDocsFor = (path: string[], node: Node<ts.Node>): string[] => {
|
||||
const pathStr = path.join('.');
|
||||
|
||||
let type: Type<ts.Type>;
|
||||
if (node.isKind(ts.SyntaxKind.InterfaceDeclaration)) {
|
||||
type = node.getType();
|
||||
} else if (node.isKind(ts.SyntaxKind.PropertySignature)) {
|
||||
type = node.getTypeNodeOrThrow()?.getType();
|
||||
} else if (node.isKind(ts.SyntaxKind.MethodSignature)) {
|
||||
type = node.getType();
|
||||
} else {
|
||||
throw Error('Unsupported type node: ' + node.getKindName());
|
||||
}
|
||||
|
||||
if (type.isObject() && !type.isArray() && !CUSTOM_TYPES[pathStr]) {
|
||||
return type.getProperties().flatMap((property) => {
|
||||
const childPath = [...path, property.getName()];
|
||||
|
||||
return getDocsFor(childPath, property.getDeclarations()[0]);
|
||||
});
|
||||
}
|
||||
|
||||
if ('getJsDocs' in node) {
|
||||
const lines: string[] = [];
|
||||
const docs = (node as unknown as JSDocableNode).getJsDocs();
|
||||
let typeText: string;
|
||||
if (CUSTOM_TYPES[pathStr]) {
|
||||
typeText = CUSTOM_TYPES[pathStr];
|
||||
} else if (type.isUnion() && !type.isBoolean()) {
|
||||
typeText = type
|
||||
.getUnionTypes()
|
||||
.map((type) => type.getText())
|
||||
.join(' | ');
|
||||
} else {
|
||||
typeText = type.getText();
|
||||
}
|
||||
const defaultValue = docs
|
||||
.flatMap((doc) => doc.getTags())
|
||||
.find((tag) => tag.getTagName() === 'default')
|
||||
?.getCommentText();
|
||||
lines.push(
|
||||
'',
|
||||
`## ${pathStr}`,
|
||||
'',
|
||||
`- **Type**: \`${typeText}\``,
|
||||
`- **Default**: \`${defaultValue}\``,
|
||||
...docs.flatMap((doc) => doc.getDescription()),
|
||||
);
|
||||
return lines;
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
const lines = getDocsFor([], inlineConfigInterface);
|
||||
const text = await format(
|
||||
PREFACE +
|
||||
'\n\n' +
|
||||
readFileSync(configTemplatePath, 'utf-8').replace(
|
||||
'{{ DOCS }}',
|
||||
lines.join('\n'),
|
||||
),
|
||||
{ parser: 'markdown' },
|
||||
);
|
||||
|
||||
writeFileSync(configPath, text);
|
||||
consola.success('Generated /config.md');
|
||||
} catch (err) {
|
||||
consola.fail('Failed to generate /config.md');
|
||||
consola.error(err.message);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
name: 'docs:generate-config-docs',
|
||||
async config() {
|
||||
if (!hasGenerated) {
|
||||
hasGenerated = true;
|
||||
await generateDocs();
|
||||
}
|
||||
},
|
||||
configureServer(server: any) {
|
||||
server.watcher.add(externalTypesPath);
|
||||
},
|
||||
async handleHotUpdate(ctx: { file: string }) {
|
||||
if ([externalTypesPath, configTemplatePath].includes(ctx.file)) {
|
||||
await generateDocs();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -72,6 +72,45 @@
|
||||
.vp-doc .no-vertical-dividers td {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.vp-doc .no-vertical-dividers tr {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.VPSidebar {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-0.collapsible {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-0.collapsible .items {
|
||||
/*border-left: 1px solid var(--vp-c-divider);*/
|
||||
}
|
||||
|
||||
.VPSidebarItem.level-1 {
|
||||
padding-left: 0.75rem;
|
||||
}
|
||||
|
||||
.VPSidebar .group + .group {
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.VPSidebarItem .badge {
|
||||
display: inline-block;
|
||||
min-width: 1.6em;
|
||||
padding: 0.3em 0.4em 0.2em;
|
||||
border-radius: 1rem;
|
||||
font-size: 0.75em;
|
||||
line-height: 1;
|
||||
margin-left: 0.5rem;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
background-color: var(--vp-c-default-2);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import DefaultTheme from 'vitepress/theme';
|
||||
import Icon from '../components/Icon.vue';
|
||||
import EntrypointPatterns from '../components/EntrypointPatterns.vue';
|
||||
import UsingWxtSection from '../components/UsingWxtSection.vue';
|
||||
import ExampleList from '../components/ExampleList.vue';
|
||||
import './custom.css';
|
||||
|
||||
export default {
|
||||
@@ -10,5 +11,6 @@ export default {
|
||||
ctx.app.component('Icon', Icon);
|
||||
ctx.app.component('EntrypointPatterns', EntrypointPatterns);
|
||||
ctx.app.component('UsingWxtSection', UsingWxtSection);
|
||||
ctx.app.component('ExampleList', ExampleList);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { HeadConfig } from 'vitepress/types/shared';
|
||||
|
||||
export function meta(
|
||||
property: string,
|
||||
content: string,
|
||||
options?: { useName: boolean },
|
||||
): HeadConfig {
|
||||
return [
|
||||
'meta',
|
||||
{
|
||||
[options?.useName ? 'name' : 'property']: property,
|
||||
content,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function script(
|
||||
src: string,
|
||||
props: Record<string, string> = {},
|
||||
): HeadConfig {
|
||||
return [
|
||||
'script',
|
||||
{
|
||||
...props,
|
||||
src,
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import { DefaultTheme } from 'vitepress';
|
||||
|
||||
type SidebarItem = DefaultTheme.SidebarItem;
|
||||
type NavItem = DefaultTheme.NavItem;
|
||||
|
||||
export function navItem(text: string, link: string): NavItem {
|
||||
return { text, link };
|
||||
}
|
||||
|
||||
export function menuRoot(items: SidebarItem[]) {
|
||||
return items.map((item, index) => {
|
||||
// item.collapsed = false; // uncomment to expand all level-0 items
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
export function menuGroup(text: string, items: SidebarItem[]): SidebarItem;
|
||||
export function menuGroup(
|
||||
text: string,
|
||||
base: string,
|
||||
items: SidebarItem[],
|
||||
): SidebarItem;
|
||||
export function menuGroup(
|
||||
text: string,
|
||||
a: string | SidebarItem[],
|
||||
b?: SidebarItem[],
|
||||
): SidebarItem {
|
||||
const collapsed = true;
|
||||
if (typeof a === 'string') {
|
||||
return {
|
||||
text,
|
||||
base: a,
|
||||
items: b,
|
||||
collapsed,
|
||||
};
|
||||
}
|
||||
return {
|
||||
text,
|
||||
items: a,
|
||||
collapsed,
|
||||
};
|
||||
}
|
||||
|
||||
export function menuItems(items: SidebarItem[]) {
|
||||
return {
|
||||
items,
|
||||
};
|
||||
}
|
||||
|
||||
export function menuItem(
|
||||
text: string,
|
||||
link: string,
|
||||
items?: SidebarItem[],
|
||||
): SidebarItem {
|
||||
if (items) {
|
||||
return { text, link, items };
|
||||
}
|
||||
return { text, link };
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up and add badges to typedoc leaf sections
|
||||
*/
|
||||
export function prepareTypedocSidebar(items: SidebarItem[]) {
|
||||
// skip contents file
|
||||
const filtered = items.slice(1);
|
||||
|
||||
// remove Typedoc's collapse: true from text nodes
|
||||
const prepareItems = (items: DefaultTheme.SidebarItem[], depth = 0) => {
|
||||
for (const item of items) {
|
||||
if (item.items) {
|
||||
prepareItems(item.items, depth + 1);
|
||||
const hasLeaves = item.items.some((item) => !item.items);
|
||||
if (hasLeaves) {
|
||||
item.text += ` <span class="badge">${item.items.length}</span>`;
|
||||
}
|
||||
} else {
|
||||
delete item.collapsed;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// process
|
||||
prepareItems(filtered);
|
||||
|
||||
// return
|
||||
return filtered;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
# API Reference
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
This documentation does not exist yet.
|
||||
:::
|
||||
@@ -0,0 +1,7 @@
|
||||
# `wxt build`
|
||||
|
||||
<script setup>
|
||||
import { data } from '../../.vitepress/loaders/cli.data.ts'
|
||||
</script>
|
||||
|
||||
<div class="language-sh vp-adaptive-theme active"><pre class="shiki shiki-themes github-light github-dark vp-code"><code>{{ data.build }}</code></pre></div>
|
||||
@@ -0,0 +1,7 @@
|
||||
# `wxt clean`
|
||||
|
||||
<script setup>
|
||||
import { data } from '../../.vitepress/loaders/cli.data.ts'
|
||||
</script>
|
||||
|
||||
<div class="language-sh vp-adaptive-theme active"><pre class="shiki shiki-themes github-light github-dark vp-code"><code>{{ data.clean }}</code></pre></div>
|
||||
@@ -0,0 +1,7 @@
|
||||
# `wxt init`
|
||||
|
||||
<script setup>
|
||||
import { data } from '../../.vitepress/loaders/cli.data.ts'
|
||||
</script>
|
||||
|
||||
<div class="language-sh vp-adaptive-theme active"><pre class="shiki shiki-themes github-light github-dark vp-code"><code>{{ data.init }}</code></pre></div>
|
||||
@@ -0,0 +1,7 @@
|
||||
# `wxt prepare`
|
||||
|
||||
<script setup>
|
||||
import { data } from '../../.vitepress/loaders/cli.data.ts'
|
||||
</script>
|
||||
|
||||
<div class="language-sh vp-adaptive-theme active"><pre class="shiki shiki-themes github-light github-dark vp-code"><code>{{ data.prepare }}</code></pre></div>
|
||||
@@ -0,0 +1,9 @@
|
||||
# `wxt submit init`
|
||||
|
||||
> Alias for [`publish-browser-extension`](https://www.npmjs.com/package/publish-browser-extension)
|
||||
|
||||
<script setup>
|
||||
import { data } from '../../.vitepress/loaders/cli.data.ts'
|
||||
</script>
|
||||
|
||||
<div class="language-sh vp-adaptive-theme active"><pre class="shiki shiki-themes github-light github-dark vp-code"><code>{{ data.submitInit }}</code></pre></div>
|
||||
@@ -0,0 +1,9 @@
|
||||
# `wxt submit`
|
||||
|
||||
> Alias for [`publish-browser-extension`](https://www.npmjs.com/package/publish-browser-extension)
|
||||
|
||||
<script setup>
|
||||
import { data } from '../../.vitepress/loaders/cli.data.ts'
|
||||
</script>
|
||||
|
||||
<div class="language-sh vp-adaptive-theme active"><pre class="shiki shiki-themes github-light github-dark vp-code"><code>{{ data.submit }}</code></pre></div>
|
||||
@@ -0,0 +1,7 @@
|
||||
# `wxt zip`
|
||||
|
||||
<script setup>
|
||||
import { data } from '../../.vitepress/loaders/cli.data.ts'
|
||||
</script>
|
||||
|
||||
<div class="language-sh vp-adaptive-theme active"><pre class="shiki shiki-themes github-light github-dark vp-code"><code>{{ data.zip }}</code></pre></div>
|
||||
@@ -0,0 +1,7 @@
|
||||
# `wxt`
|
||||
|
||||
<script setup>
|
||||
import { data } from '../../.vitepress/loaders/cli.data.ts'
|
||||
</script>
|
||||
|
||||
<div class="language-sh vp-adaptive-theme active"><pre class="shiki shiki-themes github-light github-dark vp-code"><code>{{ data.wxt }}</code></pre></div>
|
||||
@@ -1,5 +0,0 @@
|
||||
# Config Reference
|
||||
|
||||
Discover all the options you can use in your `wxt.config.ts` file.
|
||||
|
||||
{{ DOCS }}
|
||||
@@ -0,0 +1,7 @@
|
||||
# Examples
|
||||
|
||||
Simple walkthroughs to accomplish common tasks or patterns with WXT.
|
||||
|
||||
<ExampleList />
|
||||
|
||||
> Full code available at [`wxt-dev/wxt-examples`](https://github.com/wxt-dev/wxt-examples)
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
WXT has two directories for storing assets like CSS, images, or fonts.
|
||||
|
||||
- `<srcDir>/public`: Store files that will be copied into the output directory as-is
|
||||
- `<srcDir>/assets`: Store files that will be processed by Vite during the build process
|
||||
- [public directory](/guide/directory-structure/public/): Store files that will be copied into the output directory as-is
|
||||
- [assets directory](/guide/directory-structure/assets): Store files that will be processed by Vite during the build process
|
||||
|
||||
## `/public` Directory
|
||||
To learn more about how to use assets at runtime from either of these directories, visit their guides linked above.
|
||||
|
||||
## Public Directory
|
||||
|
||||
Place static files like the extension icon or `_locales/` directory here. These files will be copied over to the output directory without being transformed by Vite.
|
||||
|
||||
@@ -19,67 +21,13 @@ Place static files like the extension icon or `_locales/` directory here. These
|
||||
└─ icon-128.png
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
You can reference these files by using absolute paths in HTML files or `browser.runtime.getURL` in content scripts.
|
||||
|
||||
:::code-group
|
||||
|
||||
```html [popup.html]
|
||||
<img src="/icon-128.png" />
|
||||
```
|
||||
|
||||
```ts [content.ts]
|
||||
defineContentScript({
|
||||
main() {
|
||||
const image = document.createElement('img');
|
||||
image.src = browser.runtime.getURL('/icon-128.png');
|
||||
document.body.append(image);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## `/assets` Directory
|
||||
## Assets Directory
|
||||
|
||||
Files in the assets directory will be processed by Vite. They are imported in your source code, and will be transformed or renamed in the output directory.
|
||||
|
||||
```
|
||||
<srcDir>
|
||||
└─ assets/
|
||||
├─ style.css
|
||||
├─ tailwind.css
|
||||
└─ illustration.svg
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
:::code-group
|
||||
|
||||
```html [popup.html]
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="~/assets/style.css" />
|
||||
<!-- ... -->
|
||||
</head>
|
||||
<body>
|
||||
<img src="~/illustration.svg" />
|
||||
<!-- ... -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```ts [content.ts]
|
||||
import '~/assets/style.css';
|
||||
import illustration from '~/assets/style.svg';
|
||||
|
||||
defineContentScript({
|
||||
main() {
|
||||
const image = document.createElement('img');
|
||||
image.src = illustration;
|
||||
document.body.append(image);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
# Build Targets
|
||||
|
||||
You can build an extension for any combination of browser and manifest verison. Different browsers and manifest versions support different APIs and entrypoints, so be sure to check that your extension functions as expected for each target.
|
||||
|
||||
Separate build targets are written to their own output directories:
|
||||
|
||||
```
|
||||
<rootDir>
|
||||
└─ .output
|
||||
├─ chrome-mv3
|
||||
├─ firefox-mv2
|
||||
├─ edge-mv3
|
||||
└─ ...
|
||||
```
|
||||
|
||||
## Target Browser
|
||||
|
||||
To build for a specific browser, pass the `-b --browser` flag from the CLI:
|
||||
|
||||
```
|
||||
|
||||
wxt --browser firefox
|
||||
wxt build --browser firefox
|
||||
|
||||
```
|
||||
|
||||
By default, it will build for `chrome`. When excluding the [`--mv2` or `--mv3` flags](#target-manifest-version), it will default to the commonly accepted manifest version used with that browser.
|
||||
|
||||
| Browser | Default Manifest Version |
|
||||
| ---------------- | :----------------------: |
|
||||
| `chrome` | 3 |
|
||||
| `firefox` | 2 |
|
||||
| `safari` | 2 |
|
||||
| `edge` | 3 |
|
||||
| Any other string | 3 |
|
||||
|
||||
## Target Manifest Version
|
||||
|
||||
To build for a specific manifest version, pass either the `--mv2` flag or `--mv3` flag from the CLI.
|
||||
|
||||
```sh
|
||||
wxt --mv2
|
||||
wxt build --mv2
|
||||
```
|
||||
|
||||
When the `-b --browser` flag is not passed, it defaults to `chrome`. So here, we're targetting MV2 for Chrome.
|
||||
+27
-43
@@ -1,49 +1,33 @@
|
||||
# Compare
|
||||
|
||||
Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework), another web extension framework.
|
||||
Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework) (another framework) and [CRXJS](https://crxjs.dev/vite-plugin) (a bundler plugin).
|
||||
|
||||
## Overview
|
||||
|
||||
| Features | WXT | Plasmo |
|
||||
| ---------------------------------------------------- | :-------------------------: | :--------------------------------------: |
|
||||
| Supports all browsers | ✅ | ✅ |
|
||||
| MV2 Support | ✅ | ✅ |
|
||||
| MV3 Support | ✅ | ✅ |
|
||||
| Create Extension ZIPs | ✅ | ✅ |
|
||||
| Create Firefox Sources ZIP | ✅ | ❌ |
|
||||
| First-class TypeScript support | ✅ | ✅ |
|
||||
| File based entrypoint discovery | ✅ | ✅ |
|
||||
| Inline entrypoint config | ✅ | ✅ |
|
||||
| Auto-imports | ✅ | ❌ |
|
||||
| Supports all frontend frameworks | ✅ | 🟡 Only React, Vue, and Svelte |
|
||||
| Framework specific entrypoints (like `Popup.tsx`) | 🟡 `.html` `.ts` `.tsx` | ✅ `.html` `.ts` `.tsx` `.vue` `.svelte` |
|
||||
| Automated publishing | 🟡 Coming soon | ✅ |
|
||||
| Remote Code Bundling (Google Analytics) | ✅ | ✅ |
|
||||
| Features | WXT | Plasmo | CRXJS |
|
||||
| ---------------------------------------------------- | :-------------------------: | :--------------------------------------: | :-------------------------------------: |
|
||||
| Supports all browsers | ✅ | ✅ | ✅ As of `v2.0.0-beta.23` |
|
||||
| MV2 Support | ✅ | ✅ | 🟡 Either MV2 or MV3 |
|
||||
| MV3 Support | ✅ | ✅ | 🟡 Either MV2 or MV3 |
|
||||
| Create Extension ZIPs | ✅ | ✅ | ❌ |
|
||||
| Create Firefox Sources ZIP | ✅ | ❌ | ❌ |
|
||||
| First-class TypeScript support | ✅ | ✅ | ✅ |
|
||||
| Entrypoint discovery | File based | File based | ❌ |
|
||||
| Inline entrypoint config | ✅ | ✅ | Manifest based |
|
||||
| Auto-imports | ✅ | ❌ | ❌ |
|
||||
| Supports all frontend frameworks | ✅ | 🟡 Only React, Vue, and Svelte | ✅ |
|
||||
| Framework specific entrypoints (like `Popup.tsx`) | 🟡 `.html` `.ts` `.tsx` | ✅ `.html` `.ts` `.tsx` `.vue` `.svelte` | ❌ |
|
||||
| Automated publishing | ✅ | ✅ | ❌ |
|
||||
| Remote Code Bundling (Google Analytics) | ✅ | ✅ | ❌ |
|
||||
| <strong style="opacity: 50%">Dev Mode</strong> | | |
|
||||
| `.env` Files | ✅ | ✅ |
|
||||
| Opens browser and install extension | ✅ | ❌ |
|
||||
| HMR for UIs | ✅ | 🟡 React only |
|
||||
| Reload HTML Files on Change | ✅ | 🟡 Reloads entire extension |
|
||||
| Reload Content Scripts on Change | ✅ | 🟡 Reloads entire extension |
|
||||
| Reload Background on Change | 🟡 Reloads entire extension | 🟡 Reloads entire extension |
|
||||
| <strong style="opacity: 50%">Built-in Utils</strong> | | |
|
||||
| Storage | ❌ | ✅ |
|
||||
| Messaging | ❌ | ✅ |
|
||||
| Content Script UI | ❌ | ✅ |
|
||||
|
||||
## Dev Mode
|
||||
|
||||
WXT's main goal is improving the development experience (DX) of creating web extensions. There are two things WXT does differently:
|
||||
|
||||
1. Automatically opens a browser with the extension installed when starting development
|
||||
2. Reload each part of the extension individually rather than reloading the entire extension
|
||||
|
||||
Opening a browser automatically makes it super easy to start and stop development without having to manually load the extension in your browser.
|
||||
|
||||
Reloading each part of the extension individually improves your iteration speed while developing UIs. This is because reloading the entire extension on every change will close the popup and any tabs open to an extension page, like options. If you save a file associated with a UI and a content script while working on the UI, it will randomly close because it needed to reload the extension when the content script changed. This interupts your development flow and is really annoying.
|
||||
|
||||
WXT solves this problem by reloading HTML pages and content scripts individually (when possible) to keep your UIs open while you develop them. This is a MV3 feature, so if you're developing a MV2 extension, you'll get the same dev experience as Plasmo.
|
||||
|
||||
:::info
|
||||
Unfortunately, there isn't an API for reloading the background page/service worker individually, so if you change a file used by the background, the entire extension will reload. See [Issue #53](https://github.com/wxt-dev/wxt/issues/53) for more details.
|
||||
:::
|
||||
| `.env` Files | ✅ | ✅ | ✅ |
|
||||
| Opens browser and install extension | ✅ | ❌ | ❌ |
|
||||
| HMR for UIs | ✅ | 🟡 React only | ✅ |
|
||||
| Reload HTML Files on Change | ✅ | 🟡 Reloads entire extension | ✅ |
|
||||
| Reload Content Scripts on Change | ✅ | 🟡 Reloads entire extension | ✅ |
|
||||
| Reload Background on Change | 🟡 Reloads entire extension | 🟡 Reloads entire extension | 🟡 Reloads entire extension |
|
||||
| Respects Content Script `run_at` | ✅ | ✅ | ❌ ESM-style loaders run asynchronously |
|
||||
| <strong style="opacity: 50%">Built-in Utils</strong> | | | |
|
||||
| Storage | ✅ | ✅ | ❌ |
|
||||
| Messaging | ❌ | ✅ | ❌ |
|
||||
| Content Script UI | ✅ | ✅ | ❌ |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Configuration
|
||||
|
||||
WXT's behavior can be configured via the `wxt.config.ts` file. In this file, you can add Vite plugins, change the directory strucutre of your project, and set fields on your `manifest.json`.
|
||||
By default, WXT provides sensible configuration for bundling web extensions with Vite.
|
||||
|
||||
## Config File
|
||||
|
||||
@@ -15,87 +15,43 @@ export default defineConfig({
|
||||
```
|
||||
|
||||
:::info
|
||||
See the [Config reference](/config.md) for a full list of options.
|
||||
For more information on configuring WXT via the `wxt.config.ts` file, read the dedicated [`wxt.config.ts` guide](/guide/directory-structure/wxt-config).
|
||||
:::
|
||||
|
||||
## Directory Config
|
||||
## Manifest.json
|
||||
|
||||
WXT allows you to edit several directories to your liking:
|
||||
|
||||
- `root` (default: `process.cwd()`) - Root of the WXT project
|
||||
- `srcDir` (default: `<rootDir>`) - Location of all your source code
|
||||
- `entrypointsDir` (default: `<srcDir>/entrypoints`) - Folder containing all the entrypoints.
|
||||
- `publicDir` (default: `<srcDir>/public`) - Folder containing [public assets](/get-started/assets.md)
|
||||
|
||||
### Example
|
||||
|
||||
You want a `src/` directory to contain all your source code, and you want to rename `entrypoints/` → `entries/`:
|
||||
|
||||
```
|
||||
<rootDir>
|
||||
├─ src/
|
||||
│ └─ entries/
|
||||
│ ├─ background.ts
|
||||
│ └─ ...
|
||||
└─ wxt.config.ts
|
||||
```
|
||||
|
||||
Your config would look like this:
|
||||
WXT generates your extension's `manifest.json` based on the project structure. To add additional properties, like permissions, use the [`manifest` property](/api/reference/wxt/interfaces/InlineConfig#manifest).
|
||||
|
||||
```ts
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
srcDir: 'src',
|
||||
entrypointsDir: 'entries',
|
||||
manifest: {
|
||||
permissions: ['storage'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Vite Config
|
||||
:::info
|
||||
For more information on configuring the manifest, read the dedicated [Manifest guide](/guide/key-concepts/manifest).
|
||||
:::
|
||||
|
||||
[Vite](https://vitejs.dev/) is the bundler used to build each entrypoint of your extension. Vite can be configured via the `vite` option.
|
||||
## Environment
|
||||
|
||||
See [Vite's documentation](https://vitejs.dev/config/) for configuring the bundler.
|
||||
|
||||
## Frontend Frameworks
|
||||
|
||||
Adding a framework like Vue, React, or Svelte is easy!
|
||||
|
||||
In the `wxt.config.ts` file, install and add the framework's Vite plugin to the config.
|
||||
WXT can read `.env` files, and variables are accessible via `import.meta.env.*`.
|
||||
|
||||
:::code-group
|
||||
|
||||
```ts [Vue]
|
||||
import { defineConfig } from 'wxt';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
plugins: [vue()],
|
||||
},
|
||||
});
|
||||
```sh [.env]
|
||||
VITE_OAUTH_CLIENT_ID=abc123
|
||||
```
|
||||
|
||||
```ts [React]
|
||||
import { defineConfig } from 'wxt';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
plugins: [react()],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```ts [Svelte]
|
||||
import { defineConfig } from 'wxt';
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
plugins: [svelte()],
|
||||
},
|
||||
});
|
||||
```ts [JS]
|
||||
import.meta.env.VITE_OAUTH_CLIENT_ID;
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::info
|
||||
For more information on using .env files, read the dedicated [`.env` guide](/guide/directory-structure/env).
|
||||
:::
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
# Defining Entrypoints
|
||||
# Entrypoints
|
||||
|
||||
An "entrypoint" is any HTML, JS, or CSS file that needs to be bundled and included with the extension.
|
||||
An "entrypoint" is any HTML, JS, or CSS file that needs to be bundled and included with your extension, which will be loaded and executed by the browser.
|
||||
|
||||
Entrypoints may or may not be listed in the extension's `manifest.json`.
|
||||
## Defining Entrypoints
|
||||
|
||||
## `/entrypoints` Directory
|
||||
|
||||
In WXT, entrypoints are defined by adding a file to the `entrypoints/` directory.
|
||||
|
||||
For example, a project that looks like this:
|
||||
In WXT, you create an entrypoint by adding a file to the `entrypoints/` directory.
|
||||
|
||||
```
|
||||
<rootDir>
|
||||
@@ -19,46 +15,22 @@ For example, a project that looks like this:
|
||||
└─ popup.html
|
||||
```
|
||||
|
||||
would result in the following `manifest.json`:
|
||||
Some entrypoint filesname patterns are reserved by WXT and effect how the manifest is generated.
|
||||
|
||||
```json
|
||||
{
|
||||
// ...
|
||||
"manifest_version": 3,
|
||||
"action": {
|
||||
// ...
|
||||
"default_popup": "popup.html"
|
||||
},
|
||||
"background": {
|
||||
// ...
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
// ...
|
||||
"js": ["content-scripts/content.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
- `popup` adds a `action` to the manifest
|
||||
- `background` adds a background script/service worker
|
||||
- `*.content.ts` adds a content script
|
||||
- ...
|
||||
|
||||
If a file uses a [special name recognized by WXT](/get-started/entrypoints.md), it will be added to the manifest. In this case:
|
||||
> For a full list of recognized filenames, see the the [Entrypoints Directory guide](/guide/directory-structure/entrypoints/background).
|
||||
|
||||
- `popup.html` → `action.default_popup`
|
||||
- `content.ts` → `content_scripts.0.js.0`
|
||||
- `background.ts` → `background.service_worker`
|
||||
|
||||
But not all entrypoints are added to the `manifest.json`. If the filename is not recognized by WXT, they are still built and included in the extension, but they are considered "unlisted" and are not apart of the manifest.
|
||||
|
||||
In this case, `injected.ts` gets output to `<outdir>/injected.js` and is accessible via `browser.runtime.getURL("/injected.js")`.
|
||||
|
||||
:::info
|
||||
See [`/entrypoints` folder](/guide/background.md) documentation for a full list of recognized entrypoint filenames.
|
||||
:::
|
||||
Any other files, whether JS, CSS, or HTML, is considered "unlisted". Unlisted files, like `injected.ts` from above, are just bundled to the output directory and not added to the manifest. You can still access or load them at runtime.
|
||||
|
||||
## Entrypoint Options
|
||||
|
||||
Some entrypoints, like content scripts, actions, or the background, can recieve additional options.
|
||||
Most entrypoints allow customizing their options in the file you define them in. This differs from regular web extension development, where all options are placed in the `manifest.json`.
|
||||
|
||||
WXT looks for custom options in the entrypoint, and adds them to the manifest when generated.
|
||||
|
||||
In HTML files, options are listed as `meta` tags:
|
||||
|
||||
@@ -84,5 +56,5 @@ export default defineContentScript({
|
||||
```
|
||||
|
||||
:::info
|
||||
For a full list of entrypoints and each of their options, see the [`/entrypoints` folder](/guide/background.md) documentation.
|
||||
All options for each entrypoint type is listed in the [entrypoints directory docs](/guide/directory-structure/entrypoints/background).
|
||||
:::
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
# Installation
|
||||
|
||||
Bootstrap a new project, start from scratch, or migrate an existing project.
|
||||
|
||||
:::warning 🚧 WSL Support
|
||||
**_WXT does not support [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/) yet_**. See [Issue #55](https://github.com/wxt-dev/wxt/issues/55) to track progress.
|
||||
|
||||
In the meantime, you can use `cmd` instead.
|
||||
:::
|
||||
Bootstrap a new project, start from scratch, or [migrate an existing project](/get-started/migrate-to-wxt).
|
||||
|
||||
## Bootstrap Project
|
||||
|
||||
:::code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpx wxt@latest init <project-name>
|
||||
pnpm dlx wxt@latest init <project-name>
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npx wxt@latest init <project-name>
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
# The "wxt init" command currently fails when ran with bunx.
|
||||
# Use NPX as a workaround, and select "bun" as your package
|
||||
# manager. To stay up to date with this issue, follow
|
||||
# https://github.com/wxt-dev/wxt/issues/707
|
||||
#
|
||||
# bunx wxt@latest init <project-name>
|
||||
|
||||
npx wxt@latest init <project-name>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
There are several starting templates available.
|
||||
@@ -32,51 +37,36 @@ There are several starting templates available.
|
||||
| <Icon name="Svelte" /> [`svelte`](https://github.com/wxt-dev/wxt/tree/main/templates/svelte) |
|
||||
| <Icon name="Solid" icon="https://www.solidjs.com/img/favicons/favicon-32x32.png" /> [`solid`](https://github.com/wxt-dev/wxt/tree/main/templates/solid) |
|
||||
|
||||
> All templates are in TypeScript. WXT does not support JS at this time.
|
||||
:::info
|
||||
All templates default to TypeScript. Rename the file extensions to `.js` to use JavaScript instead.
|
||||
:::
|
||||
|
||||
## From Scratch
|
||||
|
||||
Create a new NPM project:
|
||||
Initialize a project and install `wxt`:
|
||||
|
||||
:::code-group
|
||||
|
||||
```sh [pnpm]
|
||||
mkdir project-name
|
||||
cd project-name
|
||||
pnpm init
|
||||
echo 'shamefully-hoist=true' >> .npmrc
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
mkdir project-name
|
||||
cd project-name
|
||||
npm init
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
mkdir project-name
|
||||
cd project-name
|
||||
yarn init
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then install `wxt`:
|
||||
|
||||
:::code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add -D wxt
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm init
|
||||
npm i --save-dev wxt
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn init
|
||||
yarn add --dev wxt
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun init
|
||||
bun add --dev wxt
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Add your first entrypoint:
|
||||
@@ -88,7 +78,7 @@ export default defineBackground(() => {
|
||||
});
|
||||
```
|
||||
|
||||
Finally, add scripts to your `package.json`:
|
||||
And add scripts to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -104,50 +94,23 @@ Finally, add scripts to your `package.json`:
|
||||
}
|
||||
```
|
||||
|
||||
## Migrate an Existing Project
|
||||
|
||||
Before starting the migration, it is recommended to run `pnpx wxt@latest init` to see what a basic project looks like. Once you have an understanding of how WXT projects are structured, you're ready to convert the project, using the initialized project as a reference.
|
||||
|
||||
Migrating a project to WXT comes down to a few steps:
|
||||
|
||||
1. Install WXT and remove any old build tools: `pnpm i -D wxt`
|
||||
1. Refactoring/move your entrypoints to the `entrypoints` directory
|
||||
1. Moving public assets to the `public` directory
|
||||
1. Update the dev and build scripts to use WXT
|
||||
1. Ensure project is compatible with Vite, which is used under the hood to bundle your extension
|
||||
|
||||
:::info
|
||||
Since projects vary greatly in setup, [start a discussion on GitHub](https://github.com/wxt-dev/wxt/discussions/new/choose) if you need help migrating your project to WXT.
|
||||
:::
|
||||
|
||||
## Development
|
||||
|
||||
Once you've installed WXT, you can start the development server using the `dev` script.
|
||||
Once the project is setup, you can start the development server using the `dev` script.
|
||||
|
||||
```sh
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
:::tip 🎉 Well done!
|
||||
|
||||
The dev command will build the extension for development, open the browser, and reload the different parts of the extension when you save changes.
|
||||
:::
|
||||
|
||||
:::details Development Manifest
|
||||
When running the dev command, WXT will make several changes to your `manifest.json` to improve your development experience:
|
||||
|
||||
- If missing, add a background script/service worker to enable fast reloads
|
||||
- Add serveral `permissions` and `host_permissions` to enable HMR and fast reloads
|
||||
- Modify the CSP to allow connections with the dev server
|
||||
- Remove `content_scripts` and register them at runtime so they can be easily reloaded when you save a file
|
||||
|
||||
If you're an experienced web extension developer and think the dev manifest looks wrong, this is why. Run a production build with `wxt build` to see the unmodified `manifest.json`.
|
||||
:::
|
||||
|
||||
## Next Steps
|
||||
|
||||
You're ready to build your web extension!
|
||||
|
||||
- Learn how to [add entrypoints](./entrypoints.md) like the popup, options page, or content scripts
|
||||
- [Configure WXT](./configuration.md) by creating a `wxt.config.ts` file
|
||||
- Checkout [example projects](https://github.com/wxt-dev/wxt-examples) to see how to perfom common tasks with WXT
|
||||
- Read the rest of the "Get Started" pages for a high-overview of what WXT can do
|
||||
- Read the [Guide](/guide/key-concepts/manifest) to learn in-depth about each feature WXT supports
|
||||
- [Configure WXT](./configuration) by creating a `wxt.config.ts` file
|
||||
- Checkout [example projects](https://github.com/wxt-dev/wxt-examples) to see how to perform common tasks with WXT
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
---
|
||||
head:
|
||||
- - link
|
||||
- rel: canonical
|
||||
href: https://wxt.dev
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
WXT is a free and open source framework for building web extensions in an conventional, intuative, and safe way **_for all browsers_**.
|
||||
## Overview
|
||||
|
||||
WXT is a free and open source framework for building web extensions in an conventional, intuitive, and safe way **_for all browsers_**.
|
||||
|
||||
WXT is based of [Nuxt](https://nuxt.com), and aims to provide the same great DX with TypeScript, auto-imports, and an opinionated project structure.
|
||||
|
||||
@@ -8,12 +17,12 @@ WXT is based of [Nuxt](https://nuxt.com), and aims to provide the same great DX
|
||||
|
||||
## Conventions
|
||||
|
||||
WXT is an optionated framework. This helps keep projects consistent and easy to pick up.
|
||||
WXT is an opinionated framework. This helps keep projects consistent and easy to pick up.
|
||||
|
||||
- **Generated manifest**: Based on your project's file structure
|
||||
- **Entrypoint configuration**: Configure entrypoints from the same file they're declare in
|
||||
- **Type-safety is a priority**: Out-of-the-box TypeScript support with improved browser API typing
|
||||
- **Simple output file structure**: Ouptut file paths minimize the path at runtime
|
||||
- **Simple output file structure**: Output file paths minimize the path at runtime
|
||||
|
||||
## Development
|
||||
|
||||
@@ -28,5 +37,11 @@ Production builds are optimized for store review, changing as few files as possi
|
||||
In addition, WXT fully supports Firefox's source code requirements when using a bundler. It will automatically create and upload a ZIP file of your source code.
|
||||
|
||||
:::info
|
||||
See [Publishing](./publishing.md) for more info around production builds.
|
||||
See [Publishing](./publishing) for more info around production builds.
|
||||
:::
|
||||
|
||||
## New to Extension Development?
|
||||
|
||||
Most of these docs assume you have a basic understanding of how to write a chrome or web extension.
|
||||
|
||||
If you've never written a web extension before or need a refresher, follow Google's ["Hello, World!" tutorial](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world) to understand the basics.
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Migrate to WXT
|
||||
|
||||
> If you have problems migrating to WXT, feel free to ask for help in GitHub by [starting a discussion](https://github.com/wxt-dev/wxt/discussions/new?category=q-a) or in [Discord](https://discord.gg/ZFsZqGery9)!
|
||||
|
||||
## Overview
|
||||
|
||||
Always start by generating a new vanilla project and merging it into your project one file at a time.
|
||||
|
||||
```sh
|
||||
cd path/to/your/project
|
||||
pnpm dlx wxt@latest init example-wxt --template vanilla
|
||||
```
|
||||
|
||||
In general, you'll need to:
|
||||
|
||||
 <input type="checkbox" /> Install `wxt`<br />
|
||||
 <input type="checkbox" /> Update/create `package.json` scripts to use `wxt` (don't forget about `postinstall`)<br />
|
||||
 <input type="checkbox" /> Move entrypoints into `entrypoints/` directory<br />
|
||||
 <input type="checkbox" /> Move assets into either the `assets/` or `public/` directories<br />
|
||||
 <input type="checkbox" /> Move manifest.json content into `wxt.config.ts`<br />
|
||||
 <input type="checkbox" /> Convert custom import syntax to be compatible with Vite<br />
|
||||
 <input type="checkbox" /> Add a default export to JS entrypoints<br />
|
||||
 <input type="checkbox" /> Use the `browser` global instead of `chrome`<br />
|
||||
 <input type="checkbox" /> Compare final `manifest.json` files, making sure permissions and host permissions are unchanged<br />
|
||||
 <input type="checkbox" /> Extension output by `wxt build` works the same way as before the migration<br />
|
||||
|
||||
Every project is different, so there's no one-solution-fits-all to migrating your project. Just make sure `wxt dev` runs, `wxt build` results in a working extension, and the list of permissions in the `manifest.json` hasn't changed. If all that looks good, you've finished migrating your extension!
|
||||
|
||||
## Popular Tools/Frameworks
|
||||
|
||||
Here's specific steps for other popular frameworks/build tools.
|
||||
|
||||
### `vite-plugin-web-extension`
|
||||
|
||||
Since you're already using Vite, it's a simple refactor.
|
||||
|
||||
1. Install `wxt`
|
||||
2. Move and refactor your entrypoints to WXT's style (with a default export)
|
||||
3. Update package.json scripts to use `wxt`
|
||||
4. Add `"postinstall": "wxt prepare"` script
|
||||
5. Move the `manifest.json` into `wxt.config.ts`
|
||||
6. Move any custom settings from `vite.config.ts` into `wxt.config.ts`'s
|
||||
7. Compare `dist/manifest.json` to `.output/*/manifest.json`, they should have the same content as before. If not, tweak your entrypoints and config to get as close as possible.
|
||||
|
||||
### `plasmo`
|
||||
|
||||
1. Install `wxt`
|
||||
2. Move entrypoints into `entrypoints/` directory, merging the named exports used to configure your JS entrypoints into WXT's default export
|
||||
3. Move public `assets/*` into the `public/` directory
|
||||
4. If you use CSUI, migrate to WXT's `createContentScriptUi`
|
||||
5. Convert Plasmo's custom import resolutions to Vite's
|
||||
6. If importing remote code via a URL, add a `url:` prefix so it works with WXT
|
||||
7. Compare your output `manifest.json` files from before the migration to after the migration. They should have the same content. If not, tweak your entrypoints and config to get as close as possible.
|
||||
|
||||
<!--
|
||||
## Migrate an Existing Project
|
||||
|
||||
:::info
|
||||
Since projects vary greatly in setup, [start a discussion on GitHub](https://github.com/wxt-dev/wxt/discussions/new/choose) if you need help migrating your project to WXT.
|
||||
:::
|
||||
-->
|
||||
+148
-90
@@ -1,106 +1,125 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Publishing
|
||||
|
||||
WXT offers several utilities that simplify the publishing process.
|
||||
WXT will help you ZIP your extensions and submit them to the stores for review.
|
||||
|
||||
## First Time Publishing
|
||||
|
||||
If you're publishing an extension to a store for the first time, it's recommended that you manually navigate the process. Each store has unique steps and requirements that you need to familiarize yourself with.
|
||||
If you're publishing an extension to a store for the first time, you must manually navigate the process. WXT doesn't help you create listings, each store has unique steps and requirements that you need to familiarize yourself with.
|
||||
|
||||
Each store requires that a ZIP file be uploaded. You can generate these using the `wxt zip` command:
|
||||
For specific details about each store, see the stores sections below.
|
||||
|
||||
- [Chrome Web Store](#chrome-web-store)
|
||||
- [Firefox Addon Store](#firefox-addon-store)
|
||||
- [Edge Addons](#edge-addons)
|
||||
|
||||
## Automation
|
||||
|
||||
WXT provides two commands to help automate the release process:
|
||||
|
||||
- `wxt submit init`: Setup all the required secrets and options for the `wxt submit` command
|
||||
- `wxt submit`: Submit new versions of your extension for review (and publish them automatically once approved)
|
||||
|
||||
To get started, run `wxt submit init` and follow the prompts. Once finished, you should have a `.env.submit` file! WXT will use this file to submit your updates.
|
||||
|
||||
> In CI, make sure you add all the environment variables to the submit step.
|
||||
|
||||
To release an update, build all the ZIPs you plan on releasing:
|
||||
|
||||
```sh
|
||||
wxt zip
|
||||
wxt zip -b firefox
|
||||
# etc
|
||||
```
|
||||
|
||||
Generated ZIP files are stored in the `.output` directory.
|
||||
Then run the `wxt submit` command, passing in all the ZIP files you want to release. In this case, we'll do a release for all 3 major stores: Chrome Web Store, Edge Addons, and Firefox Addons Store.
|
||||
|
||||
## Automation
|
||||
If it's your first time running the command, you'll want to test your secrets by passing the `--dry-run` flag:
|
||||
|
||||
To automate releasing updates, use the [`publish-browser-extension`](https://www.npmjs.com/package/publish-browser-extension) package.
|
||||
```sh
|
||||
wxt submit --dry-run \
|
||||
--chrome-zip .output/<your-extension>-<version>-chrome.zip \
|
||||
--firefox-zip .output/<your-extension>-<version>-firefox.zip --firefox-sources-zip .output/<your-extension>-<version>-sources.zip \
|
||||
--edge-zip .output/<your-extension>-<version>-chrome.zip
|
||||
```
|
||||
|
||||
:::info
|
||||
🚧 WXT plans to eventually incorporate the `publish-browser-extension` package into its own `wxt submit` command.
|
||||
If the dry run passes, remove the flag and do the actual release:
|
||||
|
||||
```sh
|
||||
wxt submit \
|
||||
--chrome-zip .output/<your-extension>-<version>-chrome.zip \
|
||||
--firefox-zip .output/<your-extension>-<version>-firefox.zip --firefox-sources-zip .output/<your-extension>-<version>-sources.zip \
|
||||
--edge-zip .output/<your-extension>-<version>-chrome.zip
|
||||
```
|
||||
|
||||
:::tip
|
||||
If you only need to release to a single store, only pass that store's ZIP flag.
|
||||
:::
|
||||
|
||||
1. Install the necessary dependencies:
|
||||
|
||||
```sh
|
||||
pnpm add -D publish-browser-extension env-cmd
|
||||
```
|
||||
|
||||
2. Add scripts to your `package.json` file:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"submit": "env-cmd -f .env.submit -- publish-extension",
|
||||
"submit:dry": "env-cmd -f .env.submit -- publish-extension --dry-run"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Create a `.env.submit` file and include the code below. If you're not publishing to certain stores, simply ignore their respective variables.
|
||||
|
||||
```txt
|
||||
CHROME_EXTENSION_ID=""
|
||||
CHROME_CLIENT_ID=""
|
||||
CHROME_CLIENT_SECRET=""
|
||||
CHROME_REFRESH_TOKEN=""
|
||||
|
||||
FIREFOX_EXTENSION_ID=""
|
||||
FIREFOX_JWT_ISSUER=""
|
||||
FIREFOX_JWT_SECRET=""
|
||||
|
||||
EDGE_PRODUCT_ID=""
|
||||
EDGE_CLIENT_ID=""
|
||||
EDGE_CLIENT_SECRET=""
|
||||
EDGE_ACCESS_TOKEN_URL=""
|
||||
```
|
||||
|
||||
> Each value will be filled in during the next step.
|
||||
|
||||
4. Run `npx publish-extension --help` for assistance with filling out all the values. Insert the obtained values within the double quotes.
|
||||
|
||||
5. ZIP all the targets you plan to publish, in this case Chrome and Firefox.
|
||||
|
||||
```sh
|
||||
wxt zip
|
||||
wxt zip -b firefox
|
||||
```
|
||||
|
||||
6. Test your credentials by running the `submit:dry` command:
|
||||
|
||||
```sh
|
||||
pnpm submit:dry \
|
||||
--chrome-zip .output/your-extension-X.Y.Z-chrome.zip \
|
||||
--firefox-zip .output/your-extension-X.Y.Z-firefox.zip \
|
||||
--firefox-sources-zip .output/your-extension-X.Y.Z-sources.zip \
|
||||
--edge-zip .output/your-extension-X.Y.Z-chrome.zip
|
||||
```
|
||||
|
||||
7. Upload and submit your extension for review:
|
||||
|
||||
```sh
|
||||
pnpm submit \
|
||||
--chrome-zip .output/your-extension-X.Y.Z-chrome.zip \
|
||||
--firefox-zip .output/your-extension-X.Y.Z-firefox.zip \
|
||||
--firefox-sources-zip .output/your-extension-X.Y.Z-sources.zip \
|
||||
--edge-zip .output/your-extension-X.Y.Z-chrome.zip
|
||||
```
|
||||
:::tip
|
||||
See the [Firefox Addon Store](#firefox-addon-store) section for more details about the `--firefox-sources-zip` option.
|
||||
:::
|
||||
|
||||
## GitHub Action
|
||||
|
||||
Here's an example of a GitHub Action to automate submiting new versions of your extension for review. Ensure that you've added all required secrets used in the workflow to the repo's settings.
|
||||
Here's an example of a GitHub Action that submits new versions of an extension for review. Ensure that you've added all required secrets used in the workflow to the repo's settings.
|
||||
|
||||
```yml
|
||||
# TODO
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
submit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Zip extensions
|
||||
run: |
|
||||
pnpm zip
|
||||
pnpm zip:firefox
|
||||
|
||||
- name: Submit to stores
|
||||
run: |
|
||||
pnpm wxt submit \
|
||||
--chrome-zip .output/*-chrome.zip \
|
||||
--firefox-zip .output/*-firefox.zip --firefox-sources-zip .output/*-sources.zip
|
||||
env:
|
||||
CHROME_EXTENSION_ID: ${{ secrets.CHROME_EXTENSION_ID }}
|
||||
CHROME_CLIENT_ID: ${{ secrets.CHROME_CLIENT_ID }}
|
||||
CHROME_CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
|
||||
CHROME_REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }}
|
||||
FIREFOX_EXTENSION_ID: ${{ secrets.FIREFOX_EXTENSION_ID }}
|
||||
FIREFOX_JWT_ISSUER: ${{ secrets.FIREFOX_JWT_ISSUER }}
|
||||
FIREFOX_JWT_SECRET: ${{ secrets.FIREFOX_JWT_SECRET }}
|
||||
```
|
||||
|
||||
## Chrome Web Store
|
||||
The action above lays the foundation for a basic workflow, including `zip` and `submit` steps. To further enhance your GitHub Action and delve into more complex scenarios, consider exploring the following examples from real projects. They introduce advanced features such as version management, changelog generation, and GitHub releases, tailored for different needs:
|
||||
|
||||
✅ Automated • [Developer Dashboard](https://chrome.google.com/webstore/developer/dashboard) • [Publishing Docs](https://developer.chrome.com/docs/webstore/publish/)
|
||||
- [`aklinker1/github-better-line-counts`](https://github.com/aklinker1/github-better-line-counts/blob/main/.github/workflows/submit.yml) - Conventional commits, automated version bump and changelog generation, triggered manually, optional dry run for testing
|
||||
- [`GuiEpi/plex-skipper`](https://github.com/GuiEpi/plex-skipper/blob/main/.github/workflows/deploy.yml) - Triggered automatically when `package.json` version is changed, creates and uploads artifacts to GitHub release.
|
||||
|
||||
> These examples are designed to provide clear insights and are a good starting point for customizing your own workflows. Feel free to explore and adapt them to your project needs.
|
||||
|
||||
## Stores
|
||||
|
||||
### Chrome Web Store
|
||||
|
||||
> ✅ Supported • [Developer Dashboard](https://chrome.google.com/webstore/developer/dashboard) • [Publishing Docs](https://developer.chrome.com/docs/webstore/publish/)
|
||||
|
||||
To create a ZIP for Chrome:
|
||||
|
||||
@@ -108,15 +127,15 @@ To create a ZIP for Chrome:
|
||||
wxt zip
|
||||
```
|
||||
|
||||
## Firefox Addon Store
|
||||
### Firefox Addon Store
|
||||
|
||||
✅ Automated • [Developer Dashboard](https://addons.mozilla.org/developers/) • [Publishing Docs](https://extensionworkshop.com/documentation/publish/submitting-an-add-on/)
|
||||
> ✅ Supported • [Developer Dashboard](https://addons.mozilla.org/developers/) • [Publishing Docs](https://extensionworkshop.com/documentation/publish/submitting-an-add-on/)
|
||||
|
||||
Firefox requires you to upload a ZIP of your source code. This allows them to rebuild your extension and review the code in a readable way. More details can be found in [Firefox's docs](https://extensionworkshop.com/documentation/publish/source-code-submission/).
|
||||
|
||||
WXT and `publish-browser-extension` both fully support generating and automatically submitting a source code ZIP.
|
||||
WXT fully supports generating and automatically submitting a source code ZIP.
|
||||
|
||||
When you run `wxt zip -b firefox`, your sources are zipped into the `.output` directory along with your built extension. WXT is configured to exclude certain files such as config files, hidden files, and tests. However, it's important to manually check the ZIP to ensure it only contains the files necessary to rebuild your extension.
|
||||
When you run `wxt zip -b firefox`, your sources are zipped into the `.output` directory alongside the extension. WXT will automatically exclude certain files such as config files, hidden files, and tests. However, it's important to manually check the ZIP to ensure it only contains the files necessary to rebuild your extension.
|
||||
|
||||
To customize which files are zipped, add the `zip` option to your config file.
|
||||
|
||||
@@ -150,24 +169,63 @@ yarn
|
||||
yarn zip:firefox
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun i
|
||||
bun zip:firefox
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Make sure the build output is the exact same when running `wxt build -b firefox` in your main project and inside the zipped sources.
|
||||
|
||||
:::warning
|
||||
If you use a `.env` files, they can effect the chunk hashes in the output directory. Either delete the .env file before running `wxt zip -b firefox`, or include it in your sources zip with the [`zip.includeSources`](/api/reference/wxt/interfaces/InlineConfig#includesources) option. Be careful to not include any secrets in your `.env` files.
|
||||
|
||||
See Issue [#377](https://github.com/wxt-dev/wxt/issues/377) for more details.
|
||||
:::
|
||||
|
||||
Ensure that you have a `README.md` or `SOURCE_CODE_REVIEW.md` file with the above commands so that the Firefox team knows how to build your extension.
|
||||
|
||||
## Safari
|
||||
#### Private Packages
|
||||
|
||||
🚧 Not automated at this time
|
||||
If you use private packages and you don't want to provide your auth token to the Firefox team during the review process, you can use `zip.downloadPackages` to download any private packages and include them in the zip.
|
||||
|
||||
```ts
|
||||
// wxt.config.ts
|
||||
export default defineConfig({
|
||||
zip: {
|
||||
downloadPackages: [
|
||||
'@mycompany/some-package',
|
||||
//...
|
||||
],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Depending on your package manager, the `package.json` in the sources zip will be modified to use the downloaded dependencies via the `overrides` or `resolutions` field.
|
||||
|
||||
:::warning
|
||||
🚧 WXT does not currently support automated publishing for Safari. Safari extensions require a native MacOS or iOS app wrapper, which WXT cannot create at this time. For now, if you want to publish to Safari, follow this guide:
|
||||
|
||||
https://developer.apple.com/documentation/safariservices/safari_web_extensions/distributing_your_safari_web_extension
|
||||
|
||||
WXT uses the command `npm pack <package-name>` to download the package. That means regardless of your package manager, you need to properly setup a `.npmrc` file. NPM and PNPM both respect `.npmrc` files, but Yarn and Bun have their own ways of authorizing private registries, so you'll need to add an `.npmrc` file.
|
||||
:::
|
||||
|
||||
## Edge Addons
|
||||
### Safari
|
||||
|
||||
✅ Automated • [Developer Dashboard](https://aka.ms/PartnerCenterLogin) • [Publishing Docs](https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/publish/publish-extension)
|
||||
> 🚧 Not supported yet
|
||||
|
||||
WXT does not currently support automated publishing for Safari. Safari extensions require a native MacOS or iOS app wrapper, which WXT does not create yet. For now, if you want to publish to Safari, follow this guide:
|
||||
|
||||
- [Converting a web extension for Safari](https://developer.apple.com/documentation/safariservices/safari_web_extensions/converting_a_web_extension_for_safari) - "Convert your existing extension to a Safari web extension using Xcode’s command-line tool."
|
||||
|
||||
When running the `safari-web-extension-converter` CLI tool, pass the `.output/safari-mv2` or `.output/safari-mv3` directory, not your source code directory.
|
||||
|
||||
```sh
|
||||
pnpm wxt build -b safari
|
||||
xcrun safari-web-extension-converter .output/safari-mv2
|
||||
```
|
||||
|
||||
### Edge Addons
|
||||
|
||||
> ✅ Supported • [Developer Dashboard](https://aka.ms/PartnerCenterLogin) • [Publishing Docs](https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/publish/publish-extension)
|
||||
|
||||
No need to create a specific ZIP for Edge. If you're already publishing to the Chrome Web Store, you can reuse your Chrome ZIP.
|
||||
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# Testing
|
||||
|
||||
:::warning 🚧 Testing utils are not implemented yet!
|
||||
Eventually, the plan is to have an integration with Vitest.
|
||||
:::
|
||||
## Official Frameworks
|
||||
|
||||
WXT officially supports [Vitest](https://vitest.dev/) for unit tests and either [Playwright](https://playwright.dev/) or [Puppeteer](https://pptr.dev/) for E2E tests against Chromium browsers.
|
||||
|
||||
For details setting up each testing framework, see the official examples:
|
||||
|
||||
<ExampleList tag="testing" />
|
||||
|
||||
## Unofficial Frameworks
|
||||
|
||||
Puppeteer and Playwright are the only E2E test runners that support Chrome Extensions. There are no other options at the time of writing.
|
||||
|
||||
There are other options for unit tests however, like [Jest](https://jestjs.io/), [Mocha](https://mochajs.org/), or [`node:test`](https://nodejs.org/api/test.html). **_WXT does not claim to support any of them_** because none of them support all of WXT's features, like TypeScript or auto-imports.
|
||||
|
||||
If you want to try to use a different framework for unit tests, you will need to configure the environment manually:
|
||||
|
||||
- **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/go-further/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 `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/packages/wxt/src/testing/wxt-vitest-plugin.ts) for reference.
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
# Auto-imports
|
||||
|
||||
WXT uses the same tool as Nuxt for auto-imports, [`unimport`](https://github.com/unjs/unimport).
|
||||
|
||||
:::info Testing
|
||||
To setup your test environment for auto-imports, see [Testing](/get-started/testing.md).
|
||||
:::
|
||||
|
||||
## WXT Auto-imports
|
||||
|
||||
Some WXT APIs can be used without importing them:
|
||||
|
||||
- [`browser`](/config.md#browser) from `wxt/browser`, a small wrapper around `webextension-polyfill`
|
||||
- [`defineContentScript`](/config.md#defiencontentscript) from `wxt/client`
|
||||
- [`defineBackground`](/config.md#definebackgroundscript) from `wxt/client`
|
||||
|
||||
And more. All [`wxt/client`](/config.md#wxtclient) APIs can be used without imports.
|
||||
|
||||
## Project Auto-imports
|
||||
|
||||
In addition WXT APIs, default and named exports from inside the following directories can be used without listing them in imports.
|
||||
|
||||
- `<srcDir>/components/*`
|
||||
- `<srcDir>/composables/*`
|
||||
- `<srcDir>/hooks/*`
|
||||
- `<srcDir>/utils/*`
|
||||
|
||||
To add auto-imports from subdirectories, like `utils/api/some-file.ts`, re-export them from the base directory:
|
||||
|
||||
```ts
|
||||
// utils/index.ts
|
||||
export * from './api/some-file.ts';
|
||||
```
|
||||
|
||||
Alternatively, you could add the directory to the list of auto-import directories in your config file.
|
||||
|
||||
## TypeScript
|
||||
|
||||
For TypeScript to work, you need to run the `wxt prepare` command. This will ensure types are generated for auto-imports.
|
||||
|
||||
This should be added to your `postinstall` script:
|
||||
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"scripts": {
|
||||
"postinstall": "wxt prepare" // [!code ++]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
You can override the default auto-import behavior in your `wxt.config.ts` file.
|
||||
|
||||
See [`unimport`'s documentation](https://github.com/unjs/unimport#configurations) for a complete list of options.
|
||||
|
||||
```ts
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
imports: {
|
||||
// Add auto-imports for vue fuctions like createApp, ref, computed, watch, toRaw, etc...
|
||||
preset: ['vue'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
To disable auto-imports, set `imports: false`
|
||||
|
||||
```ts
|
||||
export default defineConfig({
|
||||
imports: false,
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,42 @@
|
||||
# `<srcDir>/assets`
|
||||
|
||||
Files in the assets directory will be processed by Vite. They are imported in your source code, and will be transformed or renamed in the output directory.
|
||||
|
||||
```
|
||||
<srcDir>
|
||||
└─ assets/
|
||||
├─ style.css
|
||||
└─ illustration.svg
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
:::code-group
|
||||
|
||||
```html [popup.html]
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="~/assets/style.css" />
|
||||
<!-- ... -->
|
||||
</head>
|
||||
<body>
|
||||
<img src="~/assets/illustration.svg" />
|
||||
<!-- ... -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```ts [content.ts]
|
||||
import '~/assets/style.css';
|
||||
import illustration from '~/assets/style.svg';
|
||||
|
||||
defineContentScript({
|
||||
main() {
|
||||
const image = document.createElement('img');
|
||||
image.src = illustration;
|
||||
document.body.append(image);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<srcDir>/components`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<srcDir>/composables`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -8,14 +8,15 @@ For MV2, the background is added as a script to the background page. For MV3, th
|
||||
|
||||
<EntrypointPatterns
|
||||
:patterns="[
|
||||
['background.ts', 'background.js'],
|
||||
['background.[jt]s', 'background.js'],
|
||||
['background/index.[jt]s', 'background.js'],
|
||||
]"
|
||||
/>
|
||||
|
||||
## Definition
|
||||
|
||||
:::warning
|
||||
The main function of the background **_CANNOT BE ASYNC_**. Event listeners must be added syncronously on background startup. If your main function returns a promise, WXT will log an error.
|
||||
The main function of the background **_CANNOT BE ASYNC_**. Event listeners must be added synchronously on background startup. If your main function returns a promise, WXT will log an error.
|
||||
:::
|
||||
|
||||
```ts
|
||||
+30
-8
@@ -8,10 +8,10 @@ When creating content script entrypoints, they are automatically included in the
|
||||
|
||||
<EntrypointPatterns
|
||||
:patterns="[
|
||||
['content.(ts|tsx)', 'content-scripts/content.js'],
|
||||
['content/index.(ts|tsx)', 'content-scripts/content.js'],
|
||||
['<name>.content.(ts|tsx)', 'content-scripts/<name>.js'],
|
||||
['<name>.content/index.(ts|tsx)', 'content-scripts/<name>.js'],
|
||||
['content.[jt]sx?', 'content-scripts/content.js'],
|
||||
['content/index.[jt]sx?', 'content-scripts/content.js'],
|
||||
['<name>.content.[jt]sx?', 'content-scripts/<name>.js'],
|
||||
['<name>.content/index.[jt]sx?', 'content-scripts/<name>.js'],
|
||||
]"
|
||||
/>
|
||||
|
||||
@@ -20,7 +20,7 @@ When creating content script entrypoints, they are automatically included in the
|
||||
```ts
|
||||
export default defineContentScript({
|
||||
// Set manifest options
|
||||
matches: ['*://google.com/*', '*://duckduckgo.com/*'],
|
||||
matches: string[],
|
||||
excludeMatches: undefined | [],
|
||||
includeGlobs: undefined | [],
|
||||
excludeGlobs: undefined | [],
|
||||
@@ -34,7 +34,13 @@ export default defineContentScript({
|
||||
include: undefined | string[],
|
||||
exclude: undefined | string[],
|
||||
|
||||
main() {
|
||||
// Configure how CSS is injected onto the page
|
||||
cssInjectionMode: undefined | "manifest" | "manual" | "ui",
|
||||
|
||||
// Configure how/when content script will be registered
|
||||
registration: undefined | "manifest" | "runtime",
|
||||
|
||||
main(ctx: ContentScriptContext) {
|
||||
// Executed when content script is loaded
|
||||
},
|
||||
});
|
||||
@@ -50,7 +56,7 @@ To include CSS with your content script, import the CSS file at the top of your
|
||||
|
||||
```
|
||||
|
||||
<srcDir>
|
||||
<srcDir>/
|
||||
└─ entrypoints/
|
||||
└─ overlay.content/
|
||||
├─ index.ts
|
||||
@@ -63,7 +69,8 @@ import './style.css';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['*://google.com/*', '*://duckduckgo.com/*'],
|
||||
main() {
|
||||
|
||||
main(ctx) {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
@@ -83,3 +90,18 @@ Any styles imported in your content script will be added to that content script'
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
To disable this behavior, set `cssInjectionMode` to `"manual"` or `"ui"`.
|
||||
|
||||
```ts
|
||||
export default defineContentScript({
|
||||
matches: ['*://google.com/*', '*://duckduckgo.com/*'],
|
||||
cssInjectionMode: 'manual',
|
||||
|
||||
main(ctx) {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
See [Content Script UI](/guide/key-concepts/content-script-ui) for more info on creating UIs and including CSS in content scripts.
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
WXT can build CSS entrypoints individually. CSS entrypoints are always unlisted.
|
||||
|
||||
See [Content Script CSS](/guide/content-scripts.md#css) documentation for the recomended approach to include CSS with a content script.
|
||||
See [Content Script CSS](/guide/directory-structure/entrypoints/content-scripts#css) documentation for the recommended approach to include CSS with a content script.
|
||||
|
||||
:::info
|
||||
If the recommended approach doesn't work for your use case, you can use any of the filename patterns below to build the styles separate from the JS and use the [`transformManifest` hook](/config.md#transformmanifest) to manually add your CSS file to the manifest.
|
||||
If the recommended approach doesn't work for your use case, you can use any of the filename patterns below to build the styles separate from the JS and use the [`transformManifest` hook](/api/reference/wxt/interfaces/InlineConfig#transformmanifest) to manually add your CSS file to the manifest.
|
||||
:::
|
||||
|
||||
## Filenames
|
||||
@@ -13,15 +13,12 @@
|
||||
|
||||
## Definition
|
||||
|
||||
Plain old HTML file.
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Title</title>
|
||||
<!-- Set include/exclude if the page should be removed from some builds -->
|
||||
<meta name="manifest.include" content="['chrome', ...]" />
|
||||
<meta name="manifest.exclude" content="['chrome', ...]" />
|
||||
@@ -31,3 +28,13 @@ Plain old HTML file.
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Adding UI Elements
|
||||
|
||||
Chrome extensions allow you to add panels and side panes to the devtools window.
|
||||
|
||||

|
||||
|
||||
See the WXT's examples for a full walkthrough of extending the devtools window:
|
||||
|
||||
<ExampleList tag="devtools" />
|
||||
@@ -29,6 +29,7 @@
|
||||
}"
|
||||
/>
|
||||
<meta name="manifest.type" content="page_action|browser_action" />
|
||||
<meta name="manifest.browser_style" content="true|false" />
|
||||
<!-- Set include/exclude if the page should be removed from some builds -->
|
||||
<meta name="manifest.include" content="['chrome', ...]" />
|
||||
<meta name="manifest.exclude" content="['chrome', ...]" />
|
||||
@@ -10,10 +10,10 @@ Firefox does not support sandboxed pages.
|
||||
|
||||
<EntrypointPatterns
|
||||
:patterns="[
|
||||
['entrypoints/sandbox.html', 'sandbox.html'],
|
||||
['entrypoints/sandbox/index.html', 'sandbox.html'],
|
||||
['entrypoints/<name>.sandbox.html', '<name>.html` '],
|
||||
['entrypoints/<name>.sandbox/index.html', '<name>.html` '],
|
||||
['sandbox.html', 'sandbox.html'],
|
||||
['sandbox/index.html', 'sandbox.html'],
|
||||
['<name>.sandbox.html', '<name>.html'],
|
||||
['<name>.sandbox/index.html', '<name>.html'],
|
||||
]"
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# Side Panel
|
||||
|
||||
[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/sidePanel/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Sidebars)
|
||||
|
||||
In Chrome, side panels use the "side_panel" API, while Firefox uses the "sidebar_action" API.
|
||||
|
||||
:::warning
|
||||
Chrome added support for sidepanels in Manifest V3, they are not available in Manifest V2.
|
||||
:::
|
||||
|
||||
## Filenames
|
||||
|
||||
<EntrypointPatterns
|
||||
:patterns="[
|
||||
['sidepanel.html', 'sidepanel.html'],
|
||||
['sidepanel/index.html', 'sidepanel.html'],
|
||||
['<name>.sidepanel.html', '<name>.html` '],
|
||||
['<name>.sidepanel/index.html', '<name>.html` '],
|
||||
]"
|
||||
/>
|
||||
|
||||
## Definition
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Default Side Panel Title</title>
|
||||
<meta
|
||||
name="manifest.default_icon"
|
||||
content="{
|
||||
16: '/icon-16.png',
|
||||
24: '/icon-24.png',
|
||||
...
|
||||
}"
|
||||
/>
|
||||
<meta name="manifest.open_at_install" content="true|false" />
|
||||
<meta name="manifest.browser_style" content="true|false" />
|
||||
<!-- Set include/exclude if the page should be removed from some builds -->
|
||||
<meta name="manifest.include" content="['chrome', ...]" />
|
||||
<meta name="manifest.exclude" content="['chrome', ...]" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- ... -->
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
# Unlisted Pages
|
||||
|
||||
HTML pages that are built by Vite, but are not included in the manifest.
|
||||
HTML pages that are bundled and shipped with the extension, but are not included in the manifest.
|
||||
|
||||
If you plan on using the page in an iframe, don't forget to add the page to [`web_accessible_resources`](https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources).
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -22,7 +24,7 @@ HTML pages that are built by Vite, but are not included in the manifest.
|
||||
Pages are accessible at `'/<name>.html'`:
|
||||
|
||||
```ts
|
||||
const url = browser.runtime.getURL('/<name>.html');
|
||||
const url = browser.runtime.getURL('/<name>.html', '<html></html>');
|
||||
|
||||
console.log(url); // "chrome-extension://<id>/<name>.html"
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
# Unlisted Scripts
|
||||
|
||||
TypeScript files that are bundled and shipped with the extension, but are not included in the manifest.
|
||||
|
||||
You are responsible for loading/running these scripts where needed. If necessary, don't forget to add the script and/or any related stylesheets to [`web_accessible_resources`](https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources).
|
||||
|
||||
## Filenames
|
||||
|
||||
<EntrypointPatterns
|
||||
:patterns="[
|
||||
['<name>.[jt]sx?', '<name>.js'],
|
||||
['<name>/index.[jt]sx?', '<name>.js'],
|
||||
]"
|
||||
/>
|
||||
|
||||
## Definition
|
||||
|
||||
```ts
|
||||
export default defineUnlistedScript(() => {
|
||||
// Executed when script is loaded
|
||||
});
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```ts
|
||||
export default defineUnlistedScript({
|
||||
// Set include/exclude if the script should be removed from some builds
|
||||
include: undefined | string[],
|
||||
exclude: undefined | string[],
|
||||
|
||||
// Executed when script is loaded
|
||||
main() {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<root>/.env`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<srcDir>/hooks`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<root>/.output`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<root>/package.json`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,35 @@
|
||||
# `public/`
|
||||
|
||||
Place static files like the extension icon or `_locales/` directory here. These files will be copied over to the output directory without being transformed by Vite.
|
||||
|
||||
```
|
||||
<srcDir>
|
||||
└─ public/
|
||||
├─ icon-16.png
|
||||
├─ icon-32.png
|
||||
├─ icon-48.png
|
||||
├─ icon-96.png
|
||||
└─ icon-128.png
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
You can reference these files by using absolute paths in HTML files or `browser.runtime.getURL` in content scripts.
|
||||
|
||||
:::code-group
|
||||
|
||||
```html [popup.html]
|
||||
<img src="/icon-128.png" />
|
||||
```
|
||||
|
||||
```ts [content.ts]
|
||||
defineContentScript({
|
||||
main() {
|
||||
const image = document.createElement('img');
|
||||
image.src = browser.runtime.getURL('/icon-128.png');
|
||||
document.body.append(image);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `public/_locales/`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<root>/tsconfig.json`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<srcDir>/utils`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,65 @@
|
||||
# `web-ext.config.ts`
|
||||
|
||||
This file lets you configure the browser startup when running `wxt dev`.
|
||||
|
||||
```ts
|
||||
import { defineRunnerConfig } from 'wxt';
|
||||
|
||||
export default defineRunnerConfig({
|
||||
startUrls: ['https://google.com', 'https://youtube.com'],
|
||||
});
|
||||
```
|
||||
|
||||
There are three places you can customize the runner:
|
||||
|
||||
- `<root>/wxt.config.ts` - Use the `runner` option. Changes here will be committed and shared with everyone developing the project.
|
||||
- `<root>/web-ext.config.ts` - A gitignored file for you to customize the startup behavior to your liking without effecting others
|
||||
- `$HOME/web-ext.config.ts` - Stores system-wide config effecting all projects running on your machine.
|
||||
|
||||
See below examples on how to accomplish common configuration:
|
||||
|
||||
[[toc]]
|
||||
|
||||
## Configuring Binaries
|
||||
|
||||
`web-ext`'s browser discovery is very limited. By default, it only guesses at where Chrome and Firefox are installed. If you've customized your install locations, you may need to tell `web-ext` where the binaries/executables are located using the [`binaries` option](/api/reference/wxt/interfaces/ExtensionRunnerConfig#binaries). For other Chromium based browsers, like Edge or Opera, you'll need to explicitly list them in the `binaries` option as well, otherwise they will open in Chrome by default.
|
||||
|
||||
```ts
|
||||
import { defineRunnerConfig } from 'wxt';
|
||||
|
||||
export default defineRunnerConfig({
|
||||
binaries: {
|
||||
chrome: '/path/to/chrome-beta', // Use Chrome Beta instead of regular Chrome
|
||||
firefox: 'firefoxdeveloperedition', // Use Firefox Developer Edition instead of regular Firefox
|
||||
edge: '/path/to/edge', // Open MS Edge when running "wxt -b edge"
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Disable Opening Browser
|
||||
|
||||
Disabling the browser can be useful if it's difficult to develop your extension with fresh profiles. Maybe you need to sign into a website to see a content script run, and a fresh profile isn't helpful because it doesn't save your login info.
|
||||
|
||||
To disable opening the extension automatically in a new window, just disable the runner:
|
||||
|
||||
```ts
|
||||
export default defineRunnerConfig({
|
||||
disabled: true,
|
||||
});
|
||||
```
|
||||
|
||||
## Profile Customization
|
||||
|
||||
Another option, instead of disabling the runner, to stay logged into websites is to use a custom profile.
|
||||
|
||||
`web-ext` comes with some built-in ways of using an existing profile, but it's not really using the same profile. It copies the profile to a temp directory, and uses that.
|
||||
|
||||
Instead, I've found it's better to pass Chrome's `--user-data-dir` argument. This let's you use a fresh profile initially, and customize it to your liking. You can install devtool extensions, set custom flags, and log into websites. Next time you run the extension in dev mode, all that will be remembered!
|
||||
|
||||
```ts
|
||||
export default defineRunnerConfig({
|
||||
chromiumArgs: ['--user-data-dir=./chrome-data'],
|
||||
});
|
||||
```
|
||||
|
||||
> This only works for Chrome. You'll have to use `firefoxProfile` option instead, which has the same limitations mentioned above, where you won't be signed into websites automatically.
|
||||
@@ -0,0 +1,5 @@
|
||||
# `<root>/wxt.config.ts`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# `.wxt/`
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -1,96 +0,0 @@
|
||||
# Extension APIs
|
||||
|
||||
WXT is built on top of [`webextension-polyfill`](https://www.npmjs.com/package/webextension-polyfill), which uses the standard `browser` global.
|
||||
|
||||
If you're used to Chrome's `chrome` global, its a simple switch:
|
||||
|
||||
1. Replace `chrome` with `browser`
|
||||
2. [Replace callbacks with async/await](https://developer.chrome.com/docs/extensions/mv3/promises/)
|
||||
|
||||
And that's it! Your extension now supports Chrome, Firefox, Safari, Edge, and other Chromium browsers.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
The `browser` variable is available globally via [auto-imports](/guide/auto-imports.md), or it can be imported manually.
|
||||
|
||||
```ts
|
||||
import browser from 'wxt/browser';
|
||||
```
|
||||
|
||||
The `wxt/browser` module exports a customized version of `webextension-polyfill`'s browser with improved typing.
|
||||
|
||||
### Example
|
||||
|
||||
Let's save the date the extension was installed. Just like `chrome`, some APIs require the permission is added to your manifest before the API is defined. Here, we need to add the `storage` permission to your manifest.
|
||||
|
||||
```ts
|
||||
// wxt.config.ts
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
manifest: {
|
||||
permissions: ['storage'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
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 }) => {
|
||||
if (reason === 'install') {
|
||||
browser.storage.local.setItem({ installDate: Date.now() });
|
||||
}
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Messaging
|
||||
|
||||
Follow [Chrome's message passing guide](https://developer.chrome.com/docs/extensions/mv3/messaging/) to understand how message passing works in web extensions. In Google's examples, just replace `chrome` with `browser`, and it will work in WXT.
|
||||
|
||||
Here's a basic request/response example:
|
||||
|
||||
```ts
|
||||
// popup/main.ts
|
||||
const res = await browser.runtime.sendMessage('ping');
|
||||
|
||||
console.log('res'); // "pong"
|
||||
```
|
||||
|
||||
```ts
|
||||
// background.ts
|
||||
export default defineBackground(() => {
|
||||
browser.runtime.onMessage.addEventListener(
|
||||
(message, sender, sendResponse) => {
|
||||
console.log(message); // "ping"
|
||||
|
||||
// Wait 1 second and respond with "pong"
|
||||
setTimeout(() => sendResponse('pong'), 1000);
|
||||
return true;
|
||||
},
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
There are a number of message passing libraries you can use to improve the message passing experience.
|
||||
|
||||
Here are some that are compatible with WXT (because they are based off `webextension-polyfill` as well):
|
||||
|
||||
- [`@webext-core/messaging`](https://webext-core.aklinker1.io/guide/proxy-service/) - "A light-weight, type-safe wrapper around the `browser.runtime` messaging APIs"
|
||||
- [`@webext-core/proxy-service`](https://webext-core.aklinker1.io/guide/messaging/) - "Create TRPC-like services that can be called from anywhere but run in the background"
|
||||
- [`webext-bridge`](https://github.com/zikaari/webext-bridge) - "Messaging in Web Extensions made super easy. Out of the box."
|
||||
|
||||
## Browser Differences
|
||||
|
||||
Some APIs are only available on certain browsers or manifest versions. You will have to check if an API exists at runtime if it is not in the `browser` standard.
|
||||
|
||||
```ts
|
||||
if ('session' in browser.storage) {
|
||||
// Do something with the non-standard session storage API
|
||||
}
|
||||
```
|
||||
|
||||
> If you're using TypeScript, knowing what is non-standard is easy! APIs that are not typed are non-standard.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Messaging
|
||||
|
||||
## Overview
|
||||
|
||||
Follow [Chrome's message passing guide](https://developer.chrome.com/docs/extensions/mv3/messaging/) to understand how message passing works in web extensions. In Google's examples, just replace `chrome` with `browser`, and it will work in WXT.
|
||||
|
||||
Here's a basic request/response example:
|
||||
|
||||
```ts
|
||||
// popup/main.ts
|
||||
const res = await browser.runtime.sendMessage('ping');
|
||||
|
||||
console.log(res); // "pong"
|
||||
```
|
||||
|
||||
```ts
|
||||
// background.ts
|
||||
export default defineBackground(() => {
|
||||
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
console.log(message); // "ping"
|
||||
|
||||
// Wait 1 second and respond with "pong"
|
||||
setTimeout(() => sendResponse('pong'), 1000);
|
||||
return true;
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Third Party Libraries
|
||||
|
||||
There are a number of message passing libraries you can use to improve the message passing experience.
|
||||
|
||||
- [`@webext-core/messaging`](https://webext-core.aklinker1.io/guide/messaging/) - "A light-weight, type-safe wrapper around the `browser.runtime` messaging APIs"
|
||||
- [`@webext-core/proxy-service`](https://webext-core.aklinker1.io/guide/proxy-service/) - "Create RPC-like services that can be called from anywhere but run in the background"
|
||||
- [`webext-bridge`](https://github.com/zikaari/webext-bridge) - "Messaging in Web Extensions made super easy. Out of the box."
|
||||
- [`trpc-chrome`](https://www.npmjs.com/package/trpc-chrome) - "tRPC adapter for Web Extensions 🧩"
|
||||
@@ -0,0 +1,5 @@
|
||||
# All Other APIs
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,26 @@
|
||||
# `browser.scripting`
|
||||
|
||||
[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/api/scripting) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting)
|
||||
|
||||
Refer to the browser docs above for basics on how the API works.
|
||||
|
||||
## Execute Script Return Values
|
||||
|
||||
When using `browser.scripting.executeScript`, you can execute content scripts or unlisted scripts. To return a value, just return a value from the script's main function.
|
||||
|
||||
```ts
|
||||
// entrypoints/background.ts
|
||||
const res = await browser.scripting.executeScript({
|
||||
target: { tabId },
|
||||
files: ['injected.js'],
|
||||
});
|
||||
console.log(res); // "Hello John!"
|
||||
```
|
||||
|
||||
```ts
|
||||
// entrypoints/injected.js
|
||||
export default defineContentScript(() => {
|
||||
console.log('Script was injected!');
|
||||
return 'Hello John!';
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,281 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Storage API
|
||||
|
||||
WXT provides a simplified API to replace the `browser.storage.*` APIs. Use the `storage` auto-import from `wxt/storage` or import it manually to get started:
|
||||
|
||||
```ts
|
||||
import { storage } from 'wxt/storage';
|
||||
```
|
||||
|
||||
:::warning
|
||||
To use the `wxt/storage` API, the `"storage"` permission must be added to the manifest:
|
||||
|
||||
```ts
|
||||
// wxt.config.ts
|
||||
export default defineConfig({
|
||||
manifest: {
|
||||
permissions: ['storage'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
More info on permissions [here](/guide/key-concepts/manifest#permissions).
|
||||
:::
|
||||
|
||||
[[toc]]
|
||||
|
||||
## Basic Usage
|
||||
|
||||
All storage keys must be prefixed by their storage area.
|
||||
|
||||
```ts
|
||||
// ❌ This will throw an error
|
||||
await storage.getItem('installDate');
|
||||
|
||||
// ✅ This is good
|
||||
await storage.getItem('local:installDate');
|
||||
```
|
||||
|
||||
You can use `local:`, `session:`, `sync:`, or `managed:`.
|
||||
|
||||
If you use TypeScript, you can add a type parameter to most methods to specify the expected type of the key's value:
|
||||
|
||||
```ts
|
||||
await storage.getItem<number>('local:installDate');
|
||||
await storage.watch<number>(
|
||||
'local:installDate',
|
||||
(newInstallDate, oldInstallDate) => {
|
||||
// ...
|
||||
},
|
||||
);
|
||||
await storage.getMeta<{ v: number }>('local:installDate');
|
||||
```
|
||||
|
||||
For a full list of methods available, see the [API reference](/api/reference/wxt/storage/interfaces/WxtStorage).
|
||||
|
||||
## Watchers
|
||||
|
||||
To listen for storage changes, use the `storage.watch` function. It lets you setup a listener for a single key:
|
||||
|
||||
```ts
|
||||
const unwatch = storage.watch<number>('local:counter', (newCount, oldCount) => {
|
||||
console.log('Count changed:', { newCount, oldCount });
|
||||
});
|
||||
```
|
||||
|
||||
To remove the listener, call the returned `unwatch` function:
|
||||
|
||||
```ts
|
||||
const unwatch = storage.watch(...);
|
||||
|
||||
// Some time later...
|
||||
unwatch();
|
||||
```
|
||||
|
||||
## Metadata
|
||||
|
||||
`wxt/storage` also supports setting metadata for keys, stored at `key + "$"`. Metadata is a collection of properties associated with a key. It might be a version number, last modified date, etc.
|
||||
|
||||
[Other than versioning](#versioning), you are responsible for managing a field's metadata:
|
||||
|
||||
```ts
|
||||
await Promise.all([
|
||||
storage.setItem('local:preference', true),
|
||||
storage.setMeta('local:preference', { lastModified: Date.now() }),
|
||||
]);
|
||||
```
|
||||
|
||||
When setting different properties of metadata from multiple calls, the properties are combined instead of overwritten:
|
||||
|
||||
```ts
|
||||
await storage.setMeta('local:preference', { lastModified: Date.now() });
|
||||
await storage.setMeta('local:preference', { v: 2 });
|
||||
|
||||
await storage.getMeta('local:preference'); // { v: 2, lastModified: 1703690746007 }
|
||||
```
|
||||
|
||||
You can remove all metadata associated with a key, or just specific properties:
|
||||
|
||||
```ts
|
||||
// Remove all properties
|
||||
await storage.removeMeta('local:preference');
|
||||
|
||||
// Remove one property
|
||||
await storage.removeMeta('local:preference', 'lastModified');
|
||||
|
||||
// Remove multiple properties
|
||||
await storage.removeMeta('local:preference', ['lastModified', 'v']);
|
||||
```
|
||||
|
||||
## Defining Storage Items
|
||||
|
||||
Writing the key and type parameter for the same key over and over again can be annoying. As an alternative, you can use `storage.defineItem` to create a "storage item".
|
||||
|
||||
Storage items contain the same APIs as the `storage` variable, but you can configure its type, default value, and more in a single place:
|
||||
|
||||
```ts
|
||||
// utils/storage.ts
|
||||
const showChangelogOnUpdate = storage.defineItem<boolean>(
|
||||
'local:showChangelogOnUpdate',
|
||||
{
|
||||
defaultValue: true,
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
Now, instead of using the `storage` variable, you can use the helper functions on the storage item you created:
|
||||
|
||||
```ts
|
||||
await showChangelogOnUpdate.getValue();
|
||||
await showChangelogOnUpdate.setValue(false);
|
||||
await showChangelogOnUpdate.removeValue();
|
||||
const unwatch = showChangelogOnUpdate.watch((newValue) => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
For a full list of properties and methods available, see the [API reference](/api/reference/wxt/storage/interfaces/WxtStorageItem).
|
||||
|
||||
### Versioning
|
||||
|
||||
You can add versioning to storage items if you expect them to grow or change over time. When defining the first version of an item, start with version 1.
|
||||
|
||||
For example, consider a storage item that stores a list of websites that are ignored by an extension.
|
||||
|
||||
:::code-group
|
||||
|
||||
```ts [v1]
|
||||
type IgnoredWebsiteV1 = string;
|
||||
|
||||
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV1[]>(
|
||||
'local:ignoredWebsites',
|
||||
{
|
||||
defaultValue: [],
|
||||
version: 1,
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```ts [v2]
|
||||
import { nanoid } from 'nanoid'; // [!code ++]
|
||||
|
||||
type IgnoredWebsiteV1 = string;
|
||||
interface IgnoredWebsiteV2 { // [!code ++]
|
||||
id: string; // [!code ++]
|
||||
website: string; // [!code ++]
|
||||
} // [!code ++]
|
||||
|
||||
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV1[]>( // [!code --]
|
||||
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code ++]
|
||||
'local:ignoredWebsites',
|
||||
{
|
||||
defaultValue: [],
|
||||
version: 1, // [!code --]
|
||||
version: 2, // [!code ++]
|
||||
migrations: { // [!code ++]
|
||||
// Ran when migrating from v1 to v2 // [!code ++]
|
||||
2: (websites: IgnoredWebsiteV1[]): IgnoredWebsiteV2[] => { // [!code ++]
|
||||
return websites.map((website) => ({ id: nanoid(), website })); // [!code ++]
|
||||
}, // [!code ++]
|
||||
}, // [!code ++]
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```ts [v3]
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
type IgnoredWebsiteV1 = string;
|
||||
interface IgnoredWebsiteV2 {
|
||||
id: string;
|
||||
website: string;
|
||||
}
|
||||
interface IgnoredWebsiteV3 { // [!code ++]
|
||||
id: string; // [!code ++]
|
||||
website: string; // [!code ++]
|
||||
enabled: boolean; // [!code ++]
|
||||
} // [!code ++]
|
||||
|
||||
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code --]
|
||||
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV3[]>( // [!code ++]
|
||||
'local:ignoredWebsites',
|
||||
{
|
||||
defaultValue: [],
|
||||
version: 2, // [!code --]
|
||||
version: 3, // [!code ++]
|
||||
migrations: {
|
||||
// Ran when migrating from v1 to v2
|
||||
2: (websites: IgnoredWebsiteV1[]): IgnoredWebsiteV2[] => {
|
||||
return websites.map((website) => ({ id: nanoid(), website }));
|
||||
},
|
||||
// Ran when migrating from v2 to v3 // [!code ++]
|
||||
3: (websites: IgnoredWebsiteV2[]): IgnoredWebsiteV3[] => { // [!code ++]
|
||||
return websites.map((website) => ({ ...website, enabled: true })); // [!code ++]
|
||||
}, // [!code ++]
|
||||
},
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::info
|
||||
Internally, this uses a metadata property called `v` to track the value's current version.
|
||||
:::
|
||||
|
||||
In this case, we thought that the ignored website list might change in the future, and were able to setup a versioned storage item from the start.
|
||||
|
||||
Realistically, you won't know a item needs versioned until you need to change it's schema. Thankfully, it's simple to add versioning to an unversioned storage item.
|
||||
|
||||
When a previous version isn't found, WXT assumes the version was `1`. That means you just need to set `version: 2` and add a migration for `2`, and it will just work!
|
||||
|
||||
Lets look at the same ignored websites example from before, but start with an unversioned item this time:
|
||||
|
||||
:::code-group
|
||||
|
||||
```ts [Unversioned]
|
||||
export const ignoredWebsites = storage.defineItem<string[]>(
|
||||
'local:ignoredWebsites',
|
||||
{
|
||||
defaultValue: [],
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```ts [v2]
|
||||
import { nanoid } from 'nanoid'; // [!code ++]
|
||||
|
||||
// Retroactively add a type for the first version // [!code ++]
|
||||
type IgnoredWebsiteV1 = string; // [!code ++]
|
||||
interface IgnoredWebsiteV2 { // [!code ++]
|
||||
id: string; // [!code ++]
|
||||
website: string; // [!code ++]
|
||||
} // [!code ++]
|
||||
|
||||
export const ignoredWebsites = storage.defineItem<string[]>( // [!code --]
|
||||
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code ++]
|
||||
'local:ignoredWebsites',
|
||||
{
|
||||
defaultValue: [],
|
||||
version: 2, // [!code ++]
|
||||
migrations: { // [!code ++]
|
||||
// Ran when migrating from v1 to v2 // [!code ++]
|
||||
2: (websites: IgnoredWebsiteV1[]): IgnoredWebsiteV2[] => { // [!code ++]
|
||||
return websites.map((website) => ({ id: nanoid(), website })); // [!code ++]
|
||||
}, // [!code ++]
|
||||
}, // [!code ++]
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Running Migrations
|
||||
|
||||
As soon as `storage.defineItem` is called, WXT checks if migrations need to be ran, and if so, runs them. Calls to get or update the storage item's value or metadata (`getValue`, `setValue`, `removeValue`, `getMeta`, etc) will automatically wait for the migration process to finish before actually reading or writing values.
|
||||
@@ -0,0 +1,5 @@
|
||||
# Custom Events
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,5 @@
|
||||
# Debugging
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,52 @@
|
||||
# Entrypoint Side Effects
|
||||
|
||||
You cannot use imported variables outside the `main` function in JS entrypoints. This includes options, as shown below:
|
||||
|
||||
```ts
|
||||
// entrypoints/content.ts
|
||||
import { GOOGLE_MATCHES } from '~/utils/match-patterns';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: GOOGLE_MATCHES,
|
||||
main() {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```
|
||||
$ wxt build
|
||||
wxt build
|
||||
|
||||
WXT 0.14.1
|
||||
ℹ Building chrome-mv3 for production with Vite 5.0.5
|
||||
✖ Command failed after 360 ms
|
||||
|
||||
[8:55:54 AM] ERROR entrypoints/content.ts: Cannot use imported variable "GOOGLE_MATCHES" before main function. See https://wxt.dev/guide/entrypoints.html#side-effects
|
||||
```
|
||||
|
||||
This throws an error because WXT needs to import each entrypoint during the build process to extract its definition (containing the `match`, `runAt`, `include`/`exclude`, etc.) to render the `manifest.json` correctly. Before loading an entrypoint, a transformation is applied to remove all imports. This prevents imported modules (local or NPM) with side-effects from running during the build process, potentially throwing an error.
|
||||
|
||||
:::details Why?
|
||||
|
||||
When importing your entrypoint to get its definition, the file is imported in a **_node environment_**, and doesn't have access to the `window`, `chrome`, or `browser` globals a web extension usually has access to. If WXT doesn't remove all the imports from the file, the imported modules could try and access one of these variables, throwing an error.
|
||||
|
||||
:::
|
||||
|
||||
:::warning
|
||||
See [`wxt-dev/wxt#336`](https://github.com/wxt-dev/wxt/issues/336) to track the status of this bug.
|
||||
:::
|
||||
|
||||
Usually, this error occurs when you try to extract options into a shared file or try to run code outside the `main` function. To fix the example from above, use literal values when defining an entrypoint instead of importing them:
|
||||
|
||||
```ts
|
||||
import { GOOGLE_MATCHES } from '~/utils/match-patterns'; // [!code --]
|
||||
|
||||
export default defineContentScript({
|
||||
matches: GOOGLE_MATCHES, // [!code --]
|
||||
matches: ['*//*.google.com/*'], // [!code ++]
|
||||
main() {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
# ES Modules
|
||||
|
||||
Configure entrypoints to use ESM at runtime.
|
||||
|
||||
Currently, ESM entrypoints are opt-in, so you must configure each entrypoint with that in mind.
|
||||
|
||||
## HTML Pages <Badge type="warning" text="≥0.0.1" />
|
||||
|
||||
In general, you should always make HTML pages import ESM scripts, unless you need to support old browsers.
|
||||
|
||||
To make a script ESM, add `type="module"`:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```html
|
||||
<script src="./main.ts"></script> <!-- [!code --] -->
|
||||
<script src="./main.ts" type="module"></script> <!-- [!code ++] -->
|
||||
```
|
||||
|
||||
## Background <Badge type="warning" text="≥0.16.0" />
|
||||
|
||||
In your background script, set `type: "module"`:
|
||||
|
||||
```ts
|
||||
export default defineBackground({
|
||||
type: 'module', // !code ++
|
||||
main() {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::warning
|
||||
Only MV3 support ESM background scripts/service workers. When targeting MV2, the `type` option is ignored and the background is always bundled into a single file as IIFE.
|
||||
:::
|
||||
|
||||
## Content Scripts
|
||||
|
||||
Coming soon. Follow [Content Script ESM Support #357](https://github.com/wxt-dev/wxt/issues/357) for updates.
|
||||
@@ -0,0 +1,116 @@
|
||||
# Handling Extension Updates
|
||||
|
||||
When releasing an update to your extension, there's a couple of things you need to keep in mind:
|
||||
|
||||
[[toc]]
|
||||
|
||||
## Content Script Cleanup
|
||||
|
||||
Old content scripts are not automatically stopped when an extension updates and reloads. Often, this leads to "Invalidated context" errors in production when a content script from an old version of your extension tries to use a web extension API (ie, the `browser` or `chrome` globals).
|
||||
|
||||
WXT provides a utility for handling this process: `ContentScriptContext`. An instance of this class is provided to you automatically inside the `main` function of each content script.
|
||||
|
||||
When your extension updates or reloads, the context will become invalidated, and will trigger any `ctx.onInvalidated` listeners you add:
|
||||
|
||||
```ts
|
||||
export default defineContentScript({
|
||||
main(ctx) {
|
||||
ctx.onInvalidated(() => {
|
||||
// Do something
|
||||
});
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
The `ctx` also provides other convenient APIs for stopping your content script without manually calling `onInvalidated` to add a listener:
|
||||
|
||||
1. Setting timers:
|
||||
```ts
|
||||
ctx.setTimeout(() => { ... }, ...);
|
||||
ctx.setInterval(() => { ... }, ...);
|
||||
ctx.requestAnimationFrame(() => { ... });
|
||||
```
|
||||
1. Adding DOM events:
|
||||
```ts
|
||||
ctx.addEventListener(window, "mousemove", (event) => { ... });
|
||||
```
|
||||
1. Implements [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) for canceling standard APIs:
|
||||
```ts
|
||||
fetch('...', {
|
||||
signal: ctx.signal,
|
||||
});
|
||||
```
|
||||
|
||||
Other WXT APIs require a `ctx` object so they can clean themselves up. For example, [`createIntegratedUi`](/guide/key-concepts/content-script-ui#integrated), [`createShadowRootUi`](/guide/key-concepts/content-script-ui#shadow-root), and [`createIframeUi`](/guide/key-concepts/content-script-ui#iframe) automatically unmount and stop a UI when the script is invalidated.
|
||||
|
||||
:::warning
|
||||
When working with content scripts, **you should always use the `ctx` object to stop any async or future work.**
|
||||
|
||||
This prevents old content scripts from interfering with new content scripts, and prevents error messages from being logged to the console in production.
|
||||
:::
|
||||
|
||||
## Testing Permission Changes
|
||||
|
||||
When `permissions`/`host_permissions` change during an update, depending on what exactly changed, Chrome will disable your extension until the user accepts the new permissions.
|
||||
|
||||
It is possible to test this before you release an update, but it's not a simple process:
|
||||
|
||||
1. Get 2 ZIPs of your extension, both generated by `wxt zip`. The first contains a previous version of your extension, the second contains the latest version. Make sure the second ZIP's version is higher than the first's.
|
||||
2. Unzip the two ZIP files somewhere next to each other that's easy to locate.
|
||||
3. In Chrome, open `chrome://extensions` and make sure developer mode is enabled
|
||||
4. Pack the first extension into a CRX, generating a new private key:
|
||||
1. Click "Pack Extension" in the top left
|
||||
2. For "Extension root directory", enter the path to the first extracted zip directory. The directory should contain a `manifest.json` file
|
||||
3. Leave "Private key file" blank
|
||||
4. Click "Pack Extension". This will generate a `.crx` and `.pem` file
|
||||
5. Pack the second extension into a CRX, reusing the private key generated by the previous step
|
||||
1. Click "Pack Extension" in the top left
|
||||
2. For "Extension root directory", enter the path to the second extracted zip directory.
|
||||
3. For "Private key file", enter the path to the generated `.pem` private key file
|
||||
4. Click "Pack Extension". This will generate a second `.crx` file.
|
||||
6. Install the first CRX file by dragging and dropping it onto the `chrome://extensions` page
|
||||
7. Install the second CRX file by dragging and dropping it onthe the `chrome://extensions` page
|
||||
|
||||
If a new permission must be accepted, you'll be prompted to accept it after dropping the second CRX file onto the page.
|
||||
|
||||
:::Info Note
|
||||
Note: Chrome no longer allows self-signed CRX extensions to run, but that's OK for this test case. We're still prompted to accept new permissions, even if we can't interact with the installed extension.
|
||||
|
||||
To validate this, you can create a third ZIP file with a rare permission like `geolocation` in the manifest, that's guarenteed to reprompt permissions when added.
|
||||
:::
|
||||
|
||||
## Update Event
|
||||
|
||||
You can setup a callback that runs after your extension updates like so:
|
||||
|
||||
```ts
|
||||
browser.runtime.onInstalled.addListener(({ reason }) => {
|
||||
if (reason === 'update') {
|
||||
// Do something
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
If the logic is simple, write a unit test to cover this logic. If you feel the need to manually test this callback, you can either:
|
||||
|
||||
1. In dev mode, remove the `if` statement and reload the extension from `chrome://extensions`
|
||||
2. Build two ZIPs with the same runtime ID and actually update the extension
|
||||
|
||||
The first approach is very straightforward. The second is more complicated...
|
||||
|
||||
Here are the steps:
|
||||
|
||||
So the steps:
|
||||
|
||||
1. Checkout an old commit.
|
||||
2. [Add a `key`](https://developer.chrome.com/docs/extensions/reference/manifest/key#keep-consistent-id) to the `manifest` in your `wxt.config.ts`.
|
||||
3. Run `wxt zip` to create the first ZIP.
|
||||
4. Stash or reset changes and checkout your latest code.
|
||||
5. Add back the same `key` to your manifest.
|
||||
6. Make sure the extension's version is higher than the first zip. It can be any version that's higher, since you won't be releasing this version.
|
||||
7. Run `wxt zip` to create the second ZIP.
|
||||
8. In a fresh chrome profile, go to `chrome://extensions`, enable dev mode, and drag and drop the first zip onto the page to install it.
|
||||
9. In the extension, play around and setup your test case.
|
||||
10. Back on `chrome://extensions`, drag and drop your second zip onto the page.
|
||||
|
||||
If you setup the `key` correctly, it will cause the extension to act like it was updated instead of installing a second version of your extension.
|
||||
@@ -0,0 +1,5 @@
|
||||
# How WXT Works
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -1,10 +1,10 @@
|
||||
# Remote Code
|
||||
|
||||
WXT will automatically download and bundle imports with the `url:` prefix so the extension does not depend of remote code, [a requirement from Google for MV3](https://developer.chrome.com/docs/extensions/migrating/improve-security/#remove-remote-code).
|
||||
WXT will automatically download and bundle imports with the `url:` prefix so the extension does not depend on remote code, [a requirement from Google for MV3](https://developer.chrome.com/docs/extensions/migrating/improve-security/#remove-remote-code).
|
||||
|
||||
## Google Analytics
|
||||
|
||||
For example, you can import google analytics:
|
||||
For example, you can import Google Analytics:
|
||||
|
||||
```ts
|
||||
// utils/google-analytics.ts
|
||||
@@ -0,0 +1,186 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Reusable Modules
|
||||
|
||||
## Overview
|
||||
|
||||
WXT provides a "module" API that lets you modify the build process. This API lets you add entrypoints, inject runtime code, add vite plugins, and more!
|
||||
|
||||
What's more, these modules can be shared on NPM and re-used between projects!
|
||||
|
||||
## Adding a Module
|
||||
|
||||
There are two ways to add a module to your project:
|
||||
|
||||
1. **Local file**: Any file present in the `modules/` directory will be treated as a module and loaded at build-time by WXT. You can use `modules/*.ts` or `modules/*/index.ts`, similar to entrypoints.
|
||||
|
||||
```ts
|
||||
// modules/example.ts
|
||||
import { defineWxtModule } from 'wxt/modules';
|
||||
|
||||
export default defineWxtModule((wxt) => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
2. **NPM package**: By convention, any package on NPM that starts with `@wxt-dev/module-*` or `wxt-module-*` can be installed and included in your project:
|
||||
```ts
|
||||
// wxt.config.ts
|
||||
export default defineConfig({
|
||||
// Add the module to your project
|
||||
modules: ['wxt-module-example'],
|
||||
});
|
||||
```
|
||||
|
||||
## Writing Modules
|
||||
|
||||
Modules contain a setup function that is executed at the beginning of the build process.
|
||||
|
||||
:::code-group
|
||||
|
||||
```ts [Function Definition]
|
||||
import { defineWxtModule } from 'wxt/modules';
|
||||
|
||||
export default defineWxtModule((wxt) => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```ts [Object Definition]
|
||||
import { defineWxtModule } from 'wxt/modules';
|
||||
|
||||
export default defineWxtModule({
|
||||
// Add metadata...
|
||||
setup(wxt) {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Module Options
|
||||
|
||||
You can define custom options for your module by setting the `configKey`:
|
||||
|
||||
```ts
|
||||
// modules/analytics.ts
|
||||
import { defineWxtModule } from 'wxt/modules';
|
||||
|
||||
export default defineWxtModule<AnalyticsModuleOptions>({
|
||||
configKey: 'analytics',
|
||||
setup(wxt, options) {
|
||||
console.log(options); // { clientId: "..." }
|
||||
},
|
||||
});
|
||||
|
||||
// Define the option types
|
||||
export interface AnalyticsModuleOptions {
|
||||
clientId: string;
|
||||
}
|
||||
|
||||
// Use "module augmentation" to add types for the new key
|
||||
declare module 'wxt' {
|
||||
export interface InlineConfig {
|
||||
analytics: AnalyticsModuleOptions;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now, when the user provides options to the `analytics` key in their `wxt.config.ts`, those options are passed into the setup function as the second argument.
|
||||
|
||||
```ts
|
||||
export default defineConfig({
|
||||
analytics: { clientId: '...' },
|
||||
});
|
||||
```
|
||||
|
||||
### Actually Doing Something
|
||||
|
||||
The first argument of the setup function, `wxt`, provides full access to the current build's context. You can access the resolved configuration via `wxt.config`, or setup hooks to manipulate the build at different steps of the build process.
|
||||
|
||||
Here's an example that shows you how to update the `outDir` based on the build mode. It does a good job showing how to access config, set up a hook, and do something when the hook is called.
|
||||
|
||||
```ts
|
||||
export default defineWxtModule((wxt) => {
|
||||
if (wxt.config.mode === 'development') {
|
||||
// Use the "ready" hook to update wxt.config
|
||||
wxt.hooks.hook('ready', (wxt) => {
|
||||
wxt.config.outDir = wxt.config.outDir.replace('.output', '.output/dev');
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
:::info Async Modules
|
||||
Both the `setup` function and hook callbacks can be async. Don't forget to add `await`!
|
||||
:::
|
||||
|
||||
It's important to understand the basics of how hooks work. Make sure to read the [API reference](/api/reference/wxt/interfaces/WxtHooks.html) for the full list of hooks and what they should be used for. They are the key to modifying your extension.
|
||||
|
||||
### Module Utils
|
||||
|
||||
Additionally, WXT provides several helper functions that setup hooks behind the scenes to streamline common operations.
|
||||
|
||||
For example, if you want to include an entrypoint from inside a module, you can use the `addEntrypoint` util:
|
||||
|
||||
```ts
|
||||
// modules/changelog.ts
|
||||
import { defineWxtModule, addEntrypoint } from 'wxt/modules';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
export default defineWxtModule({
|
||||
name: 'changelog',
|
||||
setup(wxt) {
|
||||
addEntrypoint(wxt, {
|
||||
type: 'unlisted-page',
|
||||
name: 'changelog',
|
||||
// Point to the "modules/changelog.html" file
|
||||
inputPath: resolve(__dirname, 'changelog.html'),
|
||||
outputDir: wxt.config.outputDir,
|
||||
options: {},
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Refer to the [API reference](/api/reference/wxt/modules/#functions) for the full list of the utilities.
|
||||
|
||||
## Plugins
|
||||
|
||||
Whereas modules are executed at build-time, plugins are executed at runtime. As of now, the only way to add a plugin is with the `addWxtPlugin` helper inside a module.
|
||||
|
||||
Here's a minimal example to execute something at runtime.
|
||||
|
||||
:::code-group
|
||||
|
||||
```ts [modules/example/index.ts]
|
||||
import { defineWxtModule, addWxtPlugin } from 'wxt/modules';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
export default defineWxtModule((wxt) => {
|
||||
addWxtPlugin(wxt, resolve(__dirname, 'plugin.ts'));
|
||||
});
|
||||
```
|
||||
|
||||
```ts [modules/example/plugin.ts]
|
||||
import { defineWxtPlugin } from 'wxt/sandbox';
|
||||
|
||||
export default defineWxtPlugin(() => {
|
||||
console.log('Executing plugin!');
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::warning Async Plugins
|
||||
Unlike modules, **_plugins cannot be async_**!! If you need to do some async work and expose that result to the rest of the extension, wrap it in an object and handle awaiting the promise internally.
|
||||
:::
|
||||
|
||||
## Publishing to NPM
|
||||
|
||||
:::warning 🚧 Under construction
|
||||
These docs will be coming soon!
|
||||
:::
|
||||
@@ -0,0 +1,25 @@
|
||||
# Testing
|
||||
|
||||
## Official Frameworks
|
||||
|
||||
WXT officially supports [Vitest](https://vitest.dev/) for unit tests and either [Playwright](https://playwright.dev/) or [Puppeteer](https://pptr.dev/) for E2E tests against Chromium browsers.
|
||||
|
||||
For details setting up each testing framework, see the official examples:
|
||||
|
||||
<ExampleList tag="testing" />
|
||||
|
||||
### Unofficial Frameworks
|
||||
|
||||
Puppeteer and Playwright are the only E2E test runners that support Chrome Extensions. There are no other options at the time of writing.
|
||||
|
||||
There are other options for unit tests however, like [Jest](https://jestjs.io/), [Mocha](https://mochajs.org/), or [`node:test`](https://nodejs.org/api/test.html). **_WXT does not claim to support any of them_** because none of them support all of WXT's features, like TypeScript or auto-imports.
|
||||
|
||||
If you want to try to use a different framework for unit tests, you will need to configure the environment manually:
|
||||
|
||||
- **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/go-further/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 `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/packages/wxt/src/testing/wxt-vitest-plugin.ts) for reference.
|
||||
@@ -10,9 +10,9 @@ All of Vite's config can be customized by setting the `vite` configuration in yo
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
vite: () => ({
|
||||
// Same as `defineConfig({ ... })` inside vite.config.ts
|
||||
},
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
@@ -26,10 +26,10 @@ All plugins should work in WXT, but it is worth pointing out that since WXT orch
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
vite: () => ({
|
||||
plugins: [
|
||||
// ...
|
||||
],
|
||||
},
|
||||
}),
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,102 @@
|
||||
# Auto-imports
|
||||
|
||||
WXT uses the same tool as Nuxt for auto-imports, [`unimport`](https://github.com/unjs/unimport).
|
||||
|
||||
## WXT Auto-imports
|
||||
|
||||
Some WXT APIs can be used without importing them:
|
||||
|
||||
- [`browser`](/api/reference/wxt/browser/variables/browser) from `wxt/browser`, a small wrapper around `webextension-polyfill`
|
||||
- [`defineContentScript`](/api/reference/wxt/sandbox/functions/defineContentScript) from `wxt/sandbox`
|
||||
- [`defineBackground`](/api/reference/wxt/sandbox/functions/defineBackground) from `wxt/sandbox`
|
||||
- [`defineUnlistedScript`](/api/reference/wxt/sandbox/functions/defineUnlistedScript) from `wxt/sandbox`
|
||||
- [`createIntegratedUi`](/api/reference/wxt/client/functions/createIntegratedUi) from `wxt/client`
|
||||
- [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) from `wxt/client`
|
||||
- [`createIframeUi`](/api/reference/wxt/client/functions/createIframeUi) from `wxt/client`
|
||||
- [`fakeBrowser`](/api/reference/wxt/testing/variables/fakeBrowser) from `wxt/testing`
|
||||
|
||||
And more!
|
||||
|
||||
## Project Auto-imports
|
||||
|
||||
In addition WXT APIs, default and named exports from inside the following directories can be used without listing them in imports.
|
||||
|
||||
- `<srcDir>/components/*`
|
||||
- `<srcDir>/composables/*`
|
||||
- `<srcDir>/hooks/*`
|
||||
- `<srcDir>/utils/*`
|
||||
|
||||
To add auto-imports from subdirectories, like `utils/api/some-file.ts`, re-export them from the base directory:
|
||||
|
||||
```ts
|
||||
// utils/index.ts
|
||||
export * from './api/some-file.ts';
|
||||
```
|
||||
|
||||
Alternatively, you could add the directory to the list of auto-import directories in your config file.
|
||||
|
||||
## TypeScript
|
||||
|
||||
For TypeScript to work, you need to run the `wxt prepare` command. This will ensure types are generated for auto-imports.
|
||||
|
||||
This should be added to your `postinstall` script so your editor has everything it needs to report type errors after installing dependencies:
|
||||
|
||||
```json
|
||||
// package.json
|
||||
{
|
||||
"scripts": {
|
||||
"postinstall": "wxt prepare" // [!code ++]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
You can override the default auto-import behavior in your `wxt.config.ts` file.
|
||||
|
||||
See [`unimport`'s documentation](https://github.com/unjs/unimport#configurations) for a complete list of options.
|
||||
|
||||
```ts
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
imports: {
|
||||
// Add auto-imports for vue functions like createApp, ref, computed, watch, toRaw, etc...
|
||||
presets: ['vue'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Disabling Auto-imports
|
||||
|
||||
To disable auto-imports, set `imports: false`
|
||||
|
||||
```ts
|
||||
export default defineConfig({
|
||||
imports: false,
|
||||
});
|
||||
```
|
||||
|
||||
## ESLint
|
||||
|
||||
ESLint doesn't understand auto-imports; it thinks all auto-imported variables are undeclared globals and will report lint errors for each. To fix this, extend the ESLint file generated inside the `.wxt` directory:
|
||||
|
||||
```js
|
||||
// .eslintrc.js
|
||||
module.exports = {
|
||||
extends: ['./.wxt/eslintrc-auto-import.json'],
|
||||
};
|
||||
```
|
||||
|
||||
By default, this file will be generated when ESLint is a direct dependency. If ESLint is a subdependency or your project is a monorepo, it may not be generated automatically. In this case, you can tell WXT to generate it:
|
||||
|
||||
```ts
|
||||
// wxt.config.ts
|
||||
export default defineConfig({
|
||||
imports: {
|
||||
eslintrc: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user