vite-userscript-plugin 1.11.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,146 +1,209 @@
1
1
  # vite-userscript-plugin
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/vite-userscript-plugin)](https://npmjs.com/vite-userscript-plugin)
4
- [![license](https://img.shields.io/github/license/crashmax-dev/vite-userscript-plugin)](./LICENCE)
5
- [![template](https://img.shields.io/github/package-json/v/crashmax-dev/vite-userscript-template?label=vite-userscript-template)](https://github.com/crashmax-dev/vite-userscript-template)
4
+ [![license](https://img.shields.io/github/license/greasify/vite-userscript-plugin)](./LICENCE)
5
+ [![template](https://img.shields.io/github/package-json/v/greasify/vite-userscript-template?label=vite-userscript-template)](https://github.com/greasify/vite-userscript-template)
6
6
 
7
- > ⚡️ A plugin for developing and building a Tampermonkey userscript based on [Vite](https://vitejs.dev).
8
-
9
- ## Table of contents
10
-
11
- - [Features](#features)
12
- - [Install](#install)
13
- - [Setup config](#setup-config)
14
- - [Using style modules](#using-style-modules)
15
- - [Plugin configuration](#plugin-configuration)
7
+ > A Vite plugin for developing and building Tampermonkey, Greasemonkey and Violentmonkey userscripts.
16
8
 
17
9
  ## Features
18
10
 
19
- - 🔥 Reloading page after changing any files.
20
- - 🔧 Configure Tampermonkey's Userscript header.
21
- - 💨 Import all [`grant`](https://www.tampermonkey.net/documentation.php#_grant)'s to the header by default in development mode.
22
- - 📝 Automatic addition of used [`grant`](https://www.tampermonkey.net/documentation.php#_grant)'s in the code when building for production.
23
- - 📦 Built-in Tampermonkey's TypeScript type definition.
11
+ - 🔥 Vite HMR
12
+ - 🔧 Configure Userscript header
13
+ - 🎨 Inject CSS from imports and SFC components (Vue, Svelte)
14
+ - 💨 All `@grant`s in the header in dev mode
15
+ - 📝 Only used `@grant`s in the production build
16
+ - 📦 Built-in types for Tampermonkey, Greasemonkey and Violentmonkey
17
+ - 📄 Virtual module with script metadata
24
18
 
25
- ## Install
19
+ ## Getting started
26
20
 
27
- ```
28
- npm install vite-userscript-plugin -D
29
- ```
30
-
31
- ```
32
- yarn add vite-userscript-plugin -D
33
- ```
21
+ Requires **Vite 8** and Node `>=22`.
34
22
 
35
- ```
23
+ ```bash
36
24
  pnpm add vite-userscript-plugin -D
37
25
  ```
38
26
 
39
- ### Setup config
40
-
41
- ```js
27
+ ```ts
42
28
  import { defineConfig } from 'vite'
43
- import Userscript from 'vite-userscript-plugin'
44
- import { name, version } from './package.json'
45
-
46
- export default defineConfig((config) => {
47
- return {
48
- plugins: [
49
- Userscript({
50
- entry: 'src/index.ts',
51
- header: {
52
- name,
53
- version,
54
- match: [
55
- 'https://example.com/',
56
- 'https://example.org/',
57
- 'https://example.edu/'
58
- ]
59
- },
60
- server: {
61
- port: 3000
62
- }
63
- })
64
- ]
65
- }
29
+ import userscript from 'vite-userscript-plugin'
30
+ import pkg from './package.json' with { type: 'json' }
31
+
32
+ export default defineConfig({
33
+ plugins: [
34
+ userscript({
35
+ entry: 'src/index.ts',
36
+ header: {
37
+ name: pkg.name,
38
+ version: pkg.version,
39
+ match: [
40
+ 'https://example.com/',
41
+ 'https://example.org/'
42
+ ]
43
+ }
44
+ })
45
+ ]
66
46
  })
67
47
  ```
68
48
 
69
- ### Setup NPM scripts
70
-
71
49
  ```json
72
- // package.json
73
50
  {
74
51
  "scripts": {
75
- "dev": "vite build --watch --mode development",
52
+ "dev": "vite",
76
53
  "build": "vite build"
77
54
  }
78
55
  }
79
56
  ```
80
57
 
81
- ### Setup TypeScript [types](https://www.typescriptlang.org/tsconfig#types)
58
+ Add types: Vite, **one** manager (`tampermonkey`, `greasemonkey`, or `violentmonkey`), and the virtual module.
59
+
60
+ `src/vite-env.d.ts`:
61
+
62
+ ```ts
63
+ /// <reference types="vite/client" />
64
+ /// <reference types="vite-userscript-plugin/types/tampermonkey" />
65
+ /// <reference types="vite-userscript-plugin/virtual" />
66
+ ```
67
+
68
+ Or `tsconfig.json`:
82
69
 
83
70
  ```json
84
- // tsconfig.json
85
71
  {
86
72
  "compilerOptions": {
87
73
  "types": [
88
- "vite-userscript-plugin/types/tampermonkey"
74
+ "vite/client",
75
+ "vite-userscript-plugin/types/tampermonkey",
76
+ "vite-userscript-plugin/virtual"
89
77
  ]
90
78
  }
91
79
  }
92
80
  ```
93
81
 
94
- ### Using style modules
82
+ Details: [types/README.md](./types/README.md).
95
83
 
96
- ```js
97
- import style from './style.css?raw'
84
+ `vite` prints `/{fileName}.dev.user.js` — install that URL once. HMR covers code and styles.
98
85
 
99
- // inject style element
100
- const styleElement = GM_addStyle(style)
86
+ `server.file: true` skips HMR. The same `vite` watch-builds `{fileName}.js` (headerless IIFE) and `{fileName}.proxy.user.js` with `@require file://` to that IIFE. Install the printed `/{fileName}.proxy.user.js` URL. See [examples/serve-file](./examples/serve-file).
101
87
 
102
- // remove style element
103
- styleElement.remove()
104
- ```
88
+ > [!IMPORTANT]
89
+ > Changing `@match`, `@grant`, or `@name` needs a reinstall.
105
90
 
106
- ## Plugin configuration
91
+ `vite build` writes `{fileName}.user.js` to `dist/`. One-shot builds do not emit the proxy.
107
92
 
108
- ```ts
109
- interface ServerConfig {
110
- /**
111
- * {@link https://github.com/sindresorhus/get-port}
112
- */
113
- port?: number;
114
-
115
- /**
116
- * @default false
117
- */
118
- open?: boolean;
119
- }
93
+ ## Multiple scripts
120
94
 
121
- interface UserscriptPluginConfig {
122
- /**
123
- * Path of userscript entry.
124
- */
125
- entry: string;
126
-
127
- /**
128
- * Userscript header config.
129
- *
130
- * @see https://www.tampermonkey.net/documentation.php
131
- */
132
- header: HeaderConfig;
133
-
134
- /**
135
- * Server config.
136
- */
137
- server?: ServerConfig;
138
- }
95
+ Pass an array of configs. Each item is one full script — no shared `header`.
96
+
97
+ See [examples/multiple-entries](./examples/multiple-entries).
98
+
99
+ ## Styles
100
+
101
+ CSS from imports and SFC `<style>` (Vue, Svelte) is collected and injected into the userscript.
102
+
103
+ ```ts
104
+ import './style.css'
139
105
  ```
140
106
 
107
+ > [!NOTE]
108
+ > Do not put userscript assets in `public/` — those URLs hit the host site and 404. Import the file so Vite inlines it.
109
+
110
+ ## HTML pages
111
+
112
+ `index.html` is a normal Vite app next to the userscript. `vite` serves it at `/`. `vite build` writes it to `dist/` beside `{fileName}.user.js`.
113
+
114
+ > [!WARNING]
115
+ > Keep the page's `<script>` entries distinct from `entry`.
116
+
117
+ Script metadata: import `virtual:vite-userscript-plugin` (`name`, `version`, `file`).
118
+
119
+ See [examples/sourcemap](./examples/sourcemap).
120
+
121
+ ## Production
122
+
123
+ `vite build` writes `{fileName}.user.js` and `{fileName}.meta.js`. `index.html` is written too, when present.
124
+
125
+ Minify is off (`build.minify`). Sourcemaps are inlined into `.user.js` when `build.sourcemap` is on.
126
+
127
+ See [examples/sourcemap](./examples/sourcemap).
128
+
129
+ ## Options
130
+
131
+ `userscript(config)` or `userscript([config, config, …])`. Options are not shared across the array.
132
+
133
+ | Option | Default | Description |
134
+ | --- | --- | --- |
135
+ | `entry` | — | Userscript entry. Required. |
136
+ | `header` | — | Metablock. Required: `name`, `version`, `match`. |
137
+ | `fileName` | sanitized `header.name` | Output base name (`{fileName}.user.js`). |
138
+ | `server.open` | `false` | Open the install target when Vite starts. HMR: `.dev.user.js`. `file`: `.proxy.user.js` URL. |
139
+ | `server.prefix` | `'server:'` | Prefix for `@name` in serve mode. `false` disables it. |
140
+ | `server.file` | `false` | Watch-build `{fileName}.js` + `{fileName}.proxy.user.js` (`@require file://`). Install from the printed URL. No HMR. |
141
+ | `cssInject` | `'auto'` | How production CSS is injected. `'auto'` uses `GM_addStyle` or a `<style>` node. |
142
+ | `align` | `1` | Extra spaces after the longest `@key`. `false` — one space. |
143
+ | `generate` | — | Rewrite the generated metablock. |
144
+ | `autoMetaUrls` | `false` | Fill empty `updateURL` / `downloadURL` from `homepage` / `homepageURL` / `website` / `source`. |
145
+ | `metaFile` | `true` | Emit `{fileName}.meta.js`. |
146
+
147
+ Everything else on `header` follows the manager metablock (`@grant`, `@require`, `@connect`, …).
148
+
149
+ In serve mode the header lists every grant. In production the plugin scans the bundle and writes only the grants in use. `grant: "none"` disables GM APIs and is never mixed with the scan.
150
+
151
+ > [!WARNING]
152
+ > Keep `metaFile: true` if you use `autoMetaUrls`. Otherwise `@updateURL` points at a file that is not emitted.
153
+
141
154
  ## Examples
142
155
 
143
- See the [examples](https://github.com/crashmax-dev/vite-userscript-plugin/tree/master/examples) folder.
156
+ | Example | What it shows |
157
+ | --- | --- |
158
+ | [basic](./examples/basic) | Vanilla + SCSS. |
159
+ | [react](./examples/react) | JSX, CSS, React refresh. |
160
+ | [vue](./examples/vue) | SFC `<style>`, minify, sourcemap. |
161
+ | [svelte](./examples/svelte) | SFC `<style>`. |
162
+ | [multiple-entries](./examples/multiple-entries) | Two scripts. |
163
+ | [sourcemap](./examples/sourcemap) | Inline map, HTML page, virtual module. |
164
+ | [serve-file](./examples/serve-file) | `server.file`, install the proxy from the printed URL. |
165
+
166
+ ## FAQ
167
+
168
+ ### Scripts fail on Firefox because of CSP
169
+
170
+ > [!WARNING]
171
+ > The host page can block Vite modules from `localhost`. Use a CSP-disable extension, or a browser profile without the site CSP.
172
+ >
173
+ > https://github.com/Tampermonkey/tampermonkey/issues/952#issuecomment-638373937
174
+
175
+ ### HTTPS site, HTTP Vite — mixed content
176
+
177
+ > [!WARNING]
178
+ > `https://example.com` will not load `http://localhost:5173`. Serve Vite over HTTPS: [`vite-plugin-mkcert`](https://github.com/liuweiGL/vite-plugin-mkcert) before `userscript()`, or `server.https`.
179
+
180
+ ### `public/` assets 404 on the target site
181
+
182
+ > [!NOTE]
183
+ > Userscripts run on someone else’s origin. Import the file so Vite inlines it. `public/` only works for the `index.html` app on the Vite origin.
184
+
185
+ ### `@run-at document-start` feels late in dev
186
+
187
+ > [!NOTE]
188
+ > Serve injects `type="module"` (async). Production is a synchronous IIFE unless you use top-level `await`. `server.file` uses that IIFE in dev too.
189
+
190
+ ### `file://` `@require` is blocked
191
+
192
+ > [!NOTE]
193
+ > Tampermonkey must allow local file access (`@require` from `file://`). Violentmonkey polls the required file after you install `{fileName}.proxy.user.js` from the printed URL. HTTP `@require` and page auto-reload are not part of this mode.
194
+
195
+ ## Migration from v1
196
+
197
+ | v1 | v2 |
198
+ | --- | --- |
199
+ | `vite build --watch` | `vite` (HMR) or `vite` + `server.file` |
200
+ | `esbuildTransformOptions` | removed |
201
+ | `server.port` | Vite `server.port` |
202
+ | minify on by default | off; set `build.minify` |
203
+ | `*.proxy.user.js` + `file://` | `server.file: true`, or HMR `.dev.user.js` |
204
+ | Vite 3–7 | Vite 8 |
205
+ | `scripts` + shared `header` | `userscript([config, config, …])` |
206
+ | `ScriptOptions` | removed |
144
207
 
145
208
  ## License
146
209