eslint-plugin-greasemonkey 1.8.4 → 1.10.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.
Files changed (45) hide show
  1. package/README.md +776 -68
  2. package/docs/LICENSE.md +1 -1
  3. package/package.json +53 -43
  4. package/src/data/apis.js +56 -53
  5. package/src/data/headers.js +65 -31
  6. package/src/data/regex.js +14 -0
  7. package/src/index.d.ts +34 -3
  8. package/src/index.js +5 -80
  9. package/src/rules/meta-order.js +5 -6
  10. package/src/rules/meta-spacing.js +11 -10
  11. package/src/rules/no-duplicate-keys.js +2 -2
  12. package/src/rules/no-insecure-fetch.js +108 -0
  13. package/src/rules/no-insecure-messaging.js +67 -0
  14. package/src/rules/no-invalid-grants.js +12 -10
  15. package/src/rules/no-invalid-headers.js +11 -11
  16. package/src/rules/no-missing-grants.js +6 -8
  17. package/src/rules/no-missing-resources.js +10 -8
  18. package/src/rules/no-sensitive-grants.js +81 -0
  19. package/src/rules/no-unused-grants.js +2 -2
  20. package/src/rules/no-unused-resources.js +10 -8
  21. package/src/rules/prefer-gm-add-style.js +67 -0
  22. package/src/rules/prefer-match.js +4 -3
  23. package/src/rules/require-homepage-pair.js +3 -4
  24. package/src/rules/require-license-header.js +27 -0
  25. package/src/rules/require-matching-localized-fields.js +2 -2
  26. package/src/rules/require-required-fields.js +2 -2
  27. package/src/rules/require-space-before-meta-key.js +4 -5
  28. package/src/rules/require-sri-hashing.js +3 -3
  29. package/src/rules/require-update-download-pair.js +3 -4
  30. package/src/rules/require-user-js-filename.js +2 -2
  31. package/src/rules/valid-field-values.js +7 -7
  32. package/src/rules/valid-icon-headers.js +74 -0
  33. package/src/rules/valid-license-header.js +73 -0
  34. package/src/rules/valid-url-headers.js +114 -0
  35. package/src/rules/valid-version-header.js +83 -0
  36. package/src/utils/api.js +11 -0
  37. package/src/utils/array.js +1 -0
  38. package/src/utils/deprecations.js +76 -0
  39. package/src/utils/init.js +106 -0
  40. package/src/utils/license.js +56 -0
  41. package/src/utils/metadata.js +31 -0
  42. package/src/utils/pkg.js +21 -0
  43. package/src/utils/rules.js +7 -0
  44. package/src/utils/template.js +21 -0
  45. package/src/utils.js +0 -119
package/README.md CHANGED
@@ -4,12 +4,12 @@
4
4
 
5
5
  <a target="_blank" href="https://www.npmjs.com/package/eslint-plugin-greasemonkey">
6
6
  <img alt="[Latest Build]" src="https://img.shields.io/npm/v/eslint-plugin-greasemonkey?logo=icinga&style=for-the-badge&label=Latest%20Build&color=32fcee"></a>
7
- <a href="#license">
7
+ <a href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/src/branch/main/docs/LICENSE.md">
8
8
  <img alt="[License: MIT]" src="https://img.shields.io/badge/License-MIT-f1f20a.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
9
9
  <a target="_blank" href="https://getnpmstats.com/?package=eslint-plugin-greasemonkey&range=last-year&interval=monthly">
10
10
  <img src="https://img.shields.io/npm/dm/eslint-plugin-greasemonkey?style=for-the-badge&logo=npm&color=black"></a>
11
- <a target="_blank" href="https://eslint.org/">
12
- <img alt="[Requires ESLint >=9.0.0]" src="https://img.shields.io/badge/Requires-ESLint_%3E%3D9.0.0-4B32C3?style=for-the-badge&logo=eslint"></a>
11
+ <a href="#usage">
12
+ <img alt="[Supports ESLint >=9.0.0 / Oxlint >=1.65.0]" src="https://img.shields.io/badge/Supports-ESLint_%3E%3D9.0.0_%2F_Oxlint_%3E%3D1.65.0-4B32C3?style=for-the-badge&logo=eslint"></a>
13
13
  <br><br>
14
14
 
15
15
  ESLint rules for Greasemonkey userscripts.
@@ -33,6 +33,8 @@ npm i -D eslint-plugin-greasemonkey
33
33
  Usage
34
34
  </h2>
35
35
 
36
+ ### <img height=15 width=auto src="https://www.google.com/s2/favicons?domain=eslint.org&sz=64"> ESLint
37
+
36
38
  Add a bundled config to your `eslint.config.*js`:
37
39
 
38
40
  ```js
@@ -52,12 +54,46 @@ export default [
52
54
  ]
53
55
  ```
54
56
 
55
- Available bundles: `recommended`, `strict` (everything), `problem` (deterministic bugs only), `tampermonkey`, `violentmonkey`, `greasemonkey`, `scriptcat`, `adguard`
56
-
57
57
  **Note:** Rule config is either a severity string (`'off'`, `'warn'`, `'error'`) or an array `[severity, options]` when the rule accepts options.
58
58
 
59
59
  ---
60
60
 
61
+ ### <img height=15 width=auto src="https://www.google.com/s2/favicons?domain=oxc.rs&sz=64"> Oxlint
62
+
63
+ Add a JS bundle to your `oxlint.config.ts` (non-JS parsing is unsupported by Oxlint):
64
+
65
+ ```ts
66
+ ...
67
+ import greasemonkey from 'eslint-plugin-greasemonkey'
68
+
69
+ export default defineConfig({
70
+ overrides: [
71
+ // other configs
72
+ {
73
+ files: ['**/*.user.js'],
74
+ jsPlugins: ['eslint-plugin-greasemonkey'],
75
+ rules: {
76
+ ...greasemonkey.configs.recommended.rules,
77
+ 'greasemonkey/no-unused-resources': 'allow', // selectively disable rule
78
+ 'greasemonkey/meta-spacing': ['deny', { spaces: 2 }] // selectively tweak rule
79
+ }
80
+ }
81
+ ]
82
+ })
83
+ ```
84
+
85
+ **Note:** Rule config is either a severity string (`'allow'`, `'warn'`, `'deny'`) or an array `[severity, options]` when the rule accepts options.
86
+
87
+ **Note:** Oxlint is typically **6-20× faster than ESLint** w/ this plugin (due to its Rust core and parallel file processing).
88
+
89
+ ---
90
+
91
+ *Available userscript bundles:* `recommended`, `strict` (everything), `problem` (deterministic bugs only), `security`, `stylistic`
92
+
93
+ *Available manager bundles:* `tampermonkey`, `violentmonkey`, `greasemonkey`, `scriptcat`, `adguard`
94
+
95
+ ---
96
+
61
97
  <h2 id="supported-rules">
62
98
  <img height=30 width=27 align="top" src="https://api.iconify.design/mdi/format-list-checks.svg?color=%232b2b2a">
63
99
  Supported rules
@@ -73,7 +109,7 @@ Available bundles: `recommended`, `strict` (everything), `problem` (deterministi
73
109
  <img height=18 alt="[Stylistic]" src="https://img.shields.io/badge/Stylistic-af68ff?style=flat-square" align="middle"></a>
74
110
  <a title="Accepts array w/ options" href="#usage">
75
111
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
76
- <a title="Copy rule URL" target="_blank"
112
+ <a title="Copy rule URL" target="_blank"
77
113
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23meta-order">
78
114
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
79
115
  </h3>
@@ -84,7 +120,7 @@ Available bundles: `recommended`, `strict` (everything), `problem` (deterministi
84
120
 
85
121
  <h4 id="meta-order-options">Options</h4>
86
122
 
87
- - `order` (default `[]`) – metadata keys in custom order (e.g. `['license', 'namespace']`) to selectively override built-in order with
123
+ - `order` (default `[]`) – metadata keys in custom order (e.g. `['license', 'namespace']`) to selectively override built-in order with – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.5.0">v1.5.0</a>]
88
124
 
89
125
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
90
126
 
@@ -132,7 +168,7 @@ If you don't care about the order of metadata fields.
132
168
  - [`no-invalid-headers`](#no-invalid-headers)
133
169
  <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
134
170
  <a title="Optimized in tampermonkey config" href="#usage"><img height=14 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
135
- <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-f01e07?style=flat-square" align="middle"></a>
171
+ <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
136
172
  <a title="Optimized in greasemonkey config" href="#usage"><img height=14 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
137
173
  <a title="Optimized in scriptcat config" href="#usage"><img height=14 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
138
174
  <a title="Optimized in adguard config" href="#usage"><img height=14 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
@@ -150,6 +186,8 @@ If you don't care about the order of metadata fields.
150
186
 
151
187
  <h3 id="meta-spacing">
152
188
  <code>meta-spacing</code>
189
+ <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">
190
+ <img height=18 align="middle" src="https://api.iconify.design/ph/flag-banner-fold-fill.svg?color=%234a4a4a"></a>
153
191
  <a title="Included in recommended config" href="#usage">
154
192
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
155
193
  <a title="Accepts eslint --fix" target="_blank" href="https://eslint.org/docs/latest/use/command-line-interface#--fix">
@@ -158,7 +196,7 @@ If you don't care about the order of metadata fields.
158
196
  <img height=18 alt="[Stylistic]" src="https://img.shields.io/badge/Stylistic-af68ff?style=flat-square" align="middle"></a>
159
197
  <a title="Accepts array w/ options" href="#usage">
160
198
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
161
- <a title="Copy rule URL" target="_blank"
199
+ <a title="Copy rule URL" target="_blank"
162
200
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23meta-spacing">
163
201
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
164
202
  </h3>
@@ -169,13 +207,13 @@ If you don't care about the order of metadata fields.
169
207
 
170
208
  <h4 id="meta-spacing-options">Options</h4>
171
209
 
172
- - `spaces` (default `3`) – minimum spaces after the longest key
210
+ - `spaces` (default `3`) – minimum spaces after the longest key – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
173
211
 
174
212
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
175
213
 
176
214
  ```diff
177
215
  /* eslint greasemonkey/meta-spacing: ['error', { spaces: 1 }] */
178
-
216
+
179
217
  // ==UserScript==
180
218
  ! // @name My Script
181
219
  // @namespace example.com
@@ -187,7 +225,7 @@ If you don't care about the order of metadata fields.
187
225
 
188
226
  ```diff
189
227
  /* eslint greasemonkey/meta-spacing: ['error', { spaces: 1 }] */
190
-
228
+
191
229
  // ==UserScript==
192
230
  - // @name My Script
193
231
  + // @name My Script
@@ -230,7 +268,7 @@ If you don't care about visual alignment in metadata blocks.
230
268
  <code>no-duplicate-keys</code>
231
269
  <a title="Included in recommended config" href="#usage">
232
270
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
233
- <a title="Copy rule URL" target="_blank"
271
+ <a title="Copy rule URL" target="_blank"
234
272
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-duplicate-keys">
235
273
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
236
274
  </h3>
@@ -294,6 +332,166 @@ If you intentionally repeat single-value keys.
294
332
 
295
333
  </details>
296
334
 
335
+ <h3 id="no-insecure-fetch">
336
+ <code>no-insecure-fetch</code>
337
+ <a title="Included in recommended config" href="#usage">
338
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
339
+ <a title="Included in security config" href="#usage">
340
+ <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
341
+ <a title="Copy rule URL" target="_blank"
342
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-insecure-fetch">
343
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
344
+ </h3>
345
+
346
+ <details>
347
+
348
+ <summary>Flags <code>fetch()</code> + XHR requests + URL fields that use <code>http://</code>.</summary>
349
+
350
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
351
+
352
+ ```diff
353
+ // ==UserScript==
354
+ ! // @require http://cdn.example.com/lib.js
355
+ ! // @resource myCSS http://cdn.example.com/style.css
356
+ // ==/UserScript==
357
+
358
+ ! fetch('http://api.example.com/data')
359
+ ! GM_xmlhttpRequest({ method: 'GET', url: 'http://api.example.com/data' })
360
+ ! GM.xmlHttpRequest({ method: 'GET', url: 'http://api.example.com/data' })
361
+ ```
362
+
363
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
364
+
365
+ ```diff
366
+ // ==UserScript==
367
+ - // @require http://cdn.example.com/lib.js
368
+ + // @require https://cdn.example.com/lib.js
369
+ - // @resource myCSS http://cdn.example.com/style.css
370
+ + // @resource myCSS https://cdn.example.com/style.css
371
+ // ==/UserScript==
372
+
373
+ - fetch('http://api.example.com/data')
374
+ + fetch('https://api.example.com/data')
375
+ - GM_xmlhttpRequest({ method: 'GET', url: 'http://api.example.com/data' })
376
+ + GM_xmlhttpRequest({ method: 'GET', url: 'https://api.example.com/data' })
377
+ - GM.xmlHttpRequest({ method: 'GET', url: 'http://api.example.com/data' })
378
+ + GM.xmlHttpRequest({ method: 'GET', url: 'https://api.example.com/data' })
379
+ ```
380
+
381
+ #### When not to use it
382
+
383
+ If you intentionally target HTTP endpoints.
384
+
385
+ #### Introduced in
386
+
387
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.9.0">v1.9.0</a> (October 18, 2026)
388
+
389
+ #### See also
390
+
391
+ - [`prefer-match`](#prefer-match)
392
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
393
+ <a title="Included in security config" href="#usage"><img height=14 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
394
+ - [`require-sri-hashing`](#require-sri-hashing)
395
+ <a title="Included in strict config" href="#usage"><img height=14 alt="[Strict]" src="https://img.shields.io/badge/Strict-ff8c42?style=flat-square" align="middle"></a>
396
+ <a title="Included in security config" href="#usage"><img height=14 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
397
+ <a title="Accepts array w/ options" href="#require-sri-hashing-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
398
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=rfc-editor.org&sz=64">&ensp;<a target="_blank" href="https://www.rfc-editor.org/info/rfc9110/">RFC 9110 — HTTP Semantics</a>
399
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=tampermonkey.net&sz=64">&ensp;<a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=GM_xmlhttpRequest">Tampermonkey — `GM_xmlhttpRequest`</a>
400
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=violentmonkey.github.io&sz=64">&ensp;<a target="_blank" href="https://violentmonkey.github.io/api/gm/#gm_xmlhttprequest">Violentmonkey — `GM.xmlHttpRequest`</a>
401
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open">MDN — `XMLHttpRequest.open()`</a>
402
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch">MDN — `fetch()`</a>
403
+
404
+ <div align="center">
405
+
406
+ [Back to index ↑][epg-rules]
407
+
408
+ </div>
409
+
410
+ ---
411
+
412
+ </details>
413
+
414
+ <h3 id="no-insecure-messaging">
415
+ <code>no-insecure-messaging</code>
416
+ <a title="Included in recommended config" href="#usage">
417
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
418
+ <a title="Included in security config" href="#usage">
419
+ <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
420
+ <a title="Accepts array w/ options" href="#usage">
421
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
422
+ <a title="Copy rule URL" target="_blank"
423
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-insecure-messaging">
424
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
425
+ </h3>
426
+
427
+ <details>
428
+
429
+ <summary>Requires origin/source validation + explicit <code>postMessage()</code> target.</summary>
430
+
431
+ <h4 id="no-insecure-messaging-options">Options</h4>
432
+
433
+ - `disallowWildcardTarget` (default `true`) – flag <code>postMessage()</code> calls that use <code>'*'</code> as <code>targetOrigin</code>
434
+
435
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
436
+
437
+ ```diff
438
+ window.addEventListener('message', event => {
439
+ ! handle(event.data)
440
+ })
441
+
442
+ unsafeWindow.addEventListener('message', event => {
443
+ ! handle(event.data)
444
+ })
445
+
446
+ ! window.postMessage(payload, '*')
447
+ ! unsafeWindow.postMessage(payload, '*')
448
+ ```
449
+
450
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
451
+
452
+ ```diff
453
+ window.addEventListener('message', event => {
454
+ + if (event.origin !== 'https://allowed-origin.com') return
455
+ handle(event.data)
456
+ })
457
+
458
+ unsafeWindow.addEventListener('message', event => {
459
+ + if (event.origin !== 'https://allowed-origin.com') return
460
+ handle(event.data)
461
+ })
462
+
463
+ - window.postMessage(payload, '*')
464
+ + window.postMessage(payload, 'https://allowed-origin.com')
465
+ - unsafeWindow.postMessage(payload, '*')
466
+ + unsafeWindow.postMessage(payload, 'https://allowed-origin.com')
467
+ ```
468
+
469
+ #### When not to use it
470
+
471
+ If you intentionally handle messages from any origin, or broadcast to any frame on the page.
472
+
473
+ #### Introduced in
474
+
475
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.9.0">v1.9.0</a> (October 18, 2026)
476
+
477
+ #### See also
478
+
479
+ - [`no-insecure-fetch`](#no-insecure-fetch)
480
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
481
+ <a title="Included in security config" href="#usage"><img height=14 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
482
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#security_concerns">MDN — `window.postMessage()` security concerns</a>
483
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/message_event">MDN — `message` event</a>
484
+
485
+ <div align="center">
486
+
487
+ [Back to index ↑][epg-rules]
488
+
489
+ </div>
490
+
491
+ ---
492
+
493
+ </details>
494
+
297
495
  <h3 id="no-invalid-grants"><a deprecated id="valid-grants"></a>
298
496
  <code>no-invalid-grants</code>
299
497
  <a title="Included in recommended config" href="#usage">
@@ -301,7 +499,7 @@ If you intentionally repeat single-value keys.
301
499
  <a title="Optimized in tampermonkey config" href="#usage">
302
500
  <img height=18 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
303
501
  <a title="Optimized in violentmonkey config" href="#usage">
304
- <img height=18 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-f01e07?style=flat-square" align="middle"></a>
502
+ <img height=18 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
305
503
  <a title="Optimized in greasemonkey config" href="#usage">
306
504
  <img height=18 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
307
505
  <a title="Optimized in scriptcat config" href="#usage">
@@ -310,7 +508,7 @@ If you intentionally repeat single-value keys.
310
508
  <img height=18 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
311
509
  <a title="Accepts array w/ options" href="#usage">
312
510
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
313
- <a title="Copy rule URL" target="_blank"
511
+ <a title="Copy rule URL" target="_blank"
314
512
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-invalid-grants">
315
513
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
316
514
  </h3>
@@ -321,21 +519,21 @@ If you intentionally repeat single-value keys.
321
519
 
322
520
  <h4 id="no-invalid-grants-options">Options</h4>
323
521
 
324
- - `target` (default `'all'`) – manager(s) whose grants to validate against (`'all'`, `'tampermonkey'`, `'violentmonkey'`, `'greasemonkey'`, `'scriptcat'`, `'adguard'`), as a single string or array
325
- - `allowedGrants` (default `[]`) – additional `@grant` values to allow beyond the built-in list (covering Tampermonkey, Violentmonkey, Greasemonkey, ScriptCat and AdGuard), as a single string or array
522
+ - `target` (default `'all'`) – manager(s) whose grants to validate against (`'all'`, `'tampermonkey'`, `'violentmonkey'`, `'greasemonkey'`, `'scriptcat'`, `'adguard'`), as a single string or array – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.2.0">v1.2.0</a>]
523
+ - `allowedGrants` (default `[]`) – additional `@grant` values to allow beyond the built-in list (covering Tampermonkey, Violentmonkey, Greasemonkey, ScriptCat and AdGuard), as a single string or array – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.2.0">v1.2.0</a>]
326
524
 
327
525
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
328
526
 
329
527
  ```diff
330
528
  /* eslint greasemonkey/no-invalid-grants: ['error', { target: 'tampermonkey' }] */
331
-
529
+
332
530
  // ==UserScript==
333
531
  // @grant GM_getTab
334
532
  ! // @grant CAT.agent.dom
335
533
  // ==/UserScript==
336
534
 
337
535
  /* eslint greasemonkey/no-invalid-grants: ['error', { target: 'scriptcat' }] */
338
-
536
+
339
537
  // ==UserScript==
340
538
  ! // @grant GM_getTab
341
539
  // @grant CAT.agent.dom
@@ -346,14 +544,14 @@ If you intentionally repeat single-value keys.
346
544
 
347
545
  ```diff
348
546
  /* eslint greasemonkey/no-invalid-grants: ['error', { target: 'tampermonkey' }] */
349
-
547
+
350
548
  // ==UserScript==
351
549
  // @grant GM_getTab
352
550
  - // @grant CAT.agent.dom
353
551
  // ==/UserScript==
354
552
 
355
553
  /* eslint greasemonkey/no-invalid-grants: ['error', { target: 'scriptcat' }] */
356
-
554
+
357
555
  // ==UserScript==
358
556
  - // @grant GM_getTab
359
557
  // @grant CAT.agent.dom
@@ -391,12 +589,14 @@ If you don't want `@grant` validation at all. For individual uncovered grants, p
391
589
 
392
590
  <h3 id="no-invalid-headers">
393
591
  <code>no-invalid-headers</code>
592
+ <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">
593
+ <img height=18 align="middle" src="https://api.iconify.design/ph/flag-banner-fold-fill.svg?color=%234a4a4a"></a>
394
594
  <a title="Included in recommended config" href="#usage">
395
595
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
396
596
  <a title="Optimized in tampermonkey config" href="#usage">
397
597
  <img height=18 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
398
598
  <a title="Optimized in violentmonkey config" href="#usage">
399
- <img height=18 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-f01e07?style=flat-square" align="middle"></a>
599
+ <img height=18 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
400
600
  <a title="Optimized in greasemonkey config" href="#usage">
401
601
  <img height=18 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
402
602
  <a title="Optimized in scriptcat config" href="#usage">
@@ -405,7 +605,7 @@ If you don't want `@grant` validation at all. For individual uncovered grants, p
405
605
  <img height=18 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
406
606
  <a title="Accepts array w/ options" href="#usage">
407
607
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
408
- <a title="Copy rule URL" target="_blank"
608
+ <a title="Copy rule URL" target="_blank"
409
609
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-invalid-headers">
410
610
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
411
611
  </h3>
@@ -416,14 +616,14 @@ If you don't want `@grant` validation at all. For individual uncovered grants, p
416
616
 
417
617
  <h4 id="no-invalid-headers-options">Options</h4>
418
618
 
419
- - `target` (default `'all'`) – manager(s) whose headers to validate against (`'all'`, `'tampermonkey'`, `'violentmonkey'`, `'greasemonkey'`, `'scriptcat'`, `'adguard'`), as a single string or array
420
- - `allowedHeaders` (default `[]`) – additional headers to allow (strings or regexes), as a single value or array
619
+ - `target` (default `'all'`) – manager(s) whose headers to validate against (`'all'`, `'tampermonkey'`, `'violentmonkey'`, `'greasemonkey'`, `'scriptcat'`, `'adguard'`), as a single string or array – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
620
+ - `allowedHeaders` (default `[]`) – additional headers to allow (strings or regexes), as a single value or array – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
421
621
 
422
622
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
423
623
 
424
624
  ```diff
425
625
  /* eslint greasemonkey/no-invalid-headers: ['error', { target: 'tampermonkey', allowedHeaders: /^\w*url$/i }] */
426
-
626
+
427
627
  // ==UserScript==
428
628
  // @name My Script
429
629
  ! // @runin normal-tabs
@@ -436,7 +636,7 @@ If you don't want `@grant` validation at all. For individual uncovered grants, p
436
636
 
437
637
  ```diff
438
638
  /* eslint greasemonkey/no-invalid-headers: ['error', { target: 'tampermonkey', allowedHeaders: /^\w*url$/i }] */
439
-
639
+
440
640
  // ==UserScript==
441
641
  // @name My Script
442
642
  - // @runin normal-tabs
@@ -460,7 +660,7 @@ If your script relies heavily on custom headers and you'd rather not maintain `a
460
660
  - [`no-invalid-grants`](#no-invalid-grants)
461
661
  <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
462
662
  <a title="Optimized in tampermonkey config" href="#usage"><img height=14 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
463
- <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-f01e07?style=flat-square" align="middle"></a>
663
+ <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
464
664
  <a title="Optimized in greasemonkey config" href="#usage"><img height=14 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
465
665
  <a title="Optimized in scriptcat config" href="#usage"><img height=14 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
466
666
  <a title="Optimized in adguard config" href="#usage"><img height=14 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
@@ -483,7 +683,7 @@ If your script relies heavily on custom headers and you'd rather not maintain `a
483
683
  <code>no-missing-grants</code>
484
684
  <a title="Included in recommended config" href="#usage">
485
685
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
486
- <a title="Copy rule URL" target="_blank"
686
+ <a title="Copy rule URL" target="_blank"
487
687
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-missing-grants">
488
688
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
489
689
  </h3>
@@ -498,7 +698,7 @@ If your script relies heavily on custom headers and you'd rather not maintain `a
498
698
  // ==UserScript==
499
699
  // @name My Script
500
700
  // ==/UserScript==
501
-
701
+
502
702
  ! GM_setValue('key', 'value')
503
703
  ```
504
704
 
@@ -509,7 +709,7 @@ If your script relies heavily on custom headers and you'd rather not maintain `a
509
709
  // @name My Script
510
710
  + // @grant GM_setValue
511
711
  // ==/UserScript==
512
-
712
+
513
713
  GM_setValue('key', 'value')
514
714
  ```
515
715
 
@@ -526,7 +726,7 @@ If you use APIs through aliases or wrappers that obscure the original call site.
526
726
  - [`no-invalid-grants`](#no-invalid-grants)
527
727
  <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
528
728
  <a title="Optimized in tampermonkey config" href="#usage"><img height=14 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
529
- <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-f01e07?style=flat-square" align="middle"></a>
729
+ <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
530
730
  <a title="Optimized in greasemonkey config" href="#usage"><img height=14 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
531
731
  <a title="Optimized in scriptcat config" href="#usage"><img height=14 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
532
732
  <a title="Optimized in adguard config" href="#usage"><img height=14 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
@@ -548,7 +748,7 @@ If you use APIs through aliases or wrappers that obscure the original call site.
548
748
  <code>no-missing-resources</code>
549
749
  <a title="Included in recommended config" href="#usage">
550
750
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
551
- <a title="Copy rule URL" target="_blank"
751
+ <a title="Copy rule URL" target="_blank"
552
752
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-missing-resources">
553
753
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
554
754
  </h3>
@@ -563,7 +763,7 @@ If you use APIs through aliases or wrappers that obscure the original call site.
563
763
  // ==UserScript==
564
764
  // @name My Script
565
765
  // ==/UserScript==
566
-
766
+
567
767
  ! const css = GM_getResourceText('myCSS')
568
768
  ```
569
769
 
@@ -574,7 +774,7 @@ If you use APIs through aliases or wrappers that obscure the original call site.
574
774
  // @name My Script
575
775
  + // @resource myCSS https://example.com/style.css
576
776
  // ==/UserScript==
577
-
777
+
578
778
  const css = GM_getResourceText('myCSS')
579
779
  ```
580
780
 
@@ -601,11 +801,102 @@ If you reference resources through an alias or computed pattern that obscures th
601
801
 
602
802
  </details>
603
803
 
804
+ <h3 id="no-sensitive-grants">
805
+ <code>no-sensitive-grants</code>
806
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">
807
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
808
+ <a title="Included in strict config" href="#usage">
809
+ <img height=18 alt="[Strict]" src="https://img.shields.io/badge/Strict-ff8c42?style=flat-square" align="middle"></a>
810
+ <a title="Included in security config" href="#usage">
811
+ <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
812
+ <a title="Accepts array w/ options" href="#usage">
813
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
814
+ <a title="Copy rule URL" target="_blank"
815
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-sensitive-grants">
816
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
817
+ </h3>
818
+
819
+ <details>
820
+
821
+ <summary>Flags security-sensitive <code>@grant</code> values and overbroad <code>@connect</code> patterns.</summary>
822
+
823
+ <h4 id="no-sensitive-grants-options">Options</h4>
824
+
825
+ - `target` (default `'all'`) – manager(s) whose sensitive-grant set to check against (`'all'`, `'tampermonkey'`, `'violentmonkey'`, `'greasemonkey'`, `'scriptcat'`, `'adguard'`), as a single string or array
826
+ - `allowedGrants` (default `[]`) – sensitive `@grant` values to explicitly allow, as a single string or array
827
+ - `allowBroadConnect` (default `false`) – permit `@connect *`, `@connect *.com`, etc. w/o reporting
828
+
829
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
830
+
831
+ ```diff
832
+ /* eslint greasemonkey/no-sensitive-grants: ['error', { allowedGrants: ['GM_xmlhttpRequest'] }] */
833
+
834
+ // ==UserScript==
835
+ ! // @connect *
836
+ // @grant GM_xmlhttpRequest
837
+ ! // @grant GM_download
838
+ ! // @grant GM_setClipboard
839
+ ! // @grant unsafeWindow
840
+ // ==/UserScript==
841
+ ```
842
+
843
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
844
+
845
+ ```diff
846
+ /* eslint greasemonkey/no-sensitive-grants: ['error', { allowedGrants: ['GM_xmlhttpRequest'] }] */
847
+
848
+ // ==UserScript==
849
+ - // @connect *
850
+ + // @connect api.example.com
851
+ // @grant GM_xmlhttpRequest
852
+ - // @grant GM_download
853
+ - // @grant GM_setClipboard
854
+ - // @grant unsafeWindow
855
+ // ==/UserScript==
856
+ ```
857
+
858
+ #### When not to use it
859
+
860
+ If you intentionally require sensitive grants, or prefer manual security review. For individual grants or `@connect` patterns you still need, prefer `allowedGrants` or `allowBroadConnect` over disabling the rule.
861
+
862
+ #### Introduced in
863
+
864
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">v1.10.0</a> (October 22, 2026)
865
+
866
+ #### See also
867
+
868
+ - [`no-invalid-grants`](#no-invalid-grants)
869
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
870
+ <a title="Optimized in tampermonkey config" href="#usage"><img height=14 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
871
+ <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
872
+ <a title="Optimized in greasemonkey config" href="#usage"><img height=14 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
873
+ <a title="Optimized in scriptcat config" href="#usage"><img height=14 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
874
+ <a title="Optimized in adguard config" href="#usage"><img height=14 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
875
+ <a title="Accepts array w/ options" href="#no-invalid-grants-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
876
+ - [`no-missing-grants`](#no-missing-grants)
877
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
878
+ - [`no-unused-grants`](#no-unused-grants)
879
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
880
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=tampermonkey.net&sz=64">&ensp;<a target="_blank" href="https://www.tampermonkey.net/documentation.php">Tampermonkey — API reference</a>
881
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=violentmonkey.github.io&sz=64">&ensp;<a target="_blank" href="https://violentmonkey.github.io/api/gm/">Violentmonkey — `GM` API</a>
882
+
883
+ <div align="center">
884
+
885
+ [Back to index ↑][epg-rules]
886
+
887
+ </div>
888
+
889
+ ---
890
+
891
+ </details>
892
+
604
893
  <h3 id="no-unused-grants">
605
894
  <code>no-unused-grants</code>
895
+ <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">
896
+ <img height=18 align="middle" src="https://api.iconify.design/ph/flag-banner-fold-fill.svg?color=%234a4a4a"></a>
606
897
  <a title="Included in recommended config" href="#usage">
607
898
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
608
- <a title="Copy rule URL" target="_blank"
899
+ <a title="Copy rule URL" target="_blank"
609
900
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-unused-grants">
610
901
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
611
902
  </h3>
@@ -628,7 +919,7 @@ If you reference resources through an alias or computed pattern that obscures th
628
919
  // ==UserScript==
629
920
  // @grant GM_setValue
630
921
  // ==/UserScript==
631
-
922
+
632
923
  + GM_setValue('key', 'value')
633
924
  ```
634
925
 
@@ -645,7 +936,7 @@ If you access the granted API through an alias or computed property rather than
645
936
  - [`no-invalid-grants`](#no-invalid-grants)
646
937
  <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
647
938
  <a title="Optimized in tampermonkey config" href="#usage"><img height=14 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
648
- <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-f01e07?style=flat-square" align="middle"></a>
939
+ <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
649
940
  <a title="Optimized in greasemonkey config" href="#usage"><img height=14 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
650
941
  <a title="Optimized in scriptcat config" href="#usage"><img height=14 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
651
942
  <a title="Optimized in adguard config" href="#usage"><img height=14 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
@@ -665,9 +956,11 @@ If you access the granted API through an alias or computed property rather than
665
956
 
666
957
  <h3 id="no-unused-resources">
667
958
  <code>no-unused-resources</code>
959
+ <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">
960
+ <img height=18 align="middle" src="https://api.iconify.design/ph/flag-banner-fold-fill.svg?color=%234a4a4a"></a>
668
961
  <a title="Included in recommended config" href="#usage">
669
962
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
670
- <a title="Copy rule URL" target="_blank"
963
+ <a title="Copy rule URL" target="_blank"
671
964
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23no-unused-resources">
672
965
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
673
966
  </h3>
@@ -690,7 +983,7 @@ If you access the granted API through an alias or computed property rather than
690
983
  // ==UserScript==
691
984
  // @resource myCSS https://example.com/style.css
692
985
  // ==/UserScript==
693
-
986
+
694
987
  + const css = GM_getResourceText('myCSS')
695
988
  ```
696
989
 
@@ -717,11 +1010,67 @@ If you pass resource names through variables or aliases rather than use them lit
717
1010
 
718
1011
  </details>
719
1012
 
1013
+ <h3 id="prefer-gm-add-style">
1014
+ <code>prefer-gm-add-style</code>
1015
+ <a title="Only included in strict config" href="#usage">
1016
+ <img height=18 alt="[Strict only]" src="https://img.shields.io/badge/Strict_only-ff8c42?style=flat-square" align="middle"></a>
1017
+ <a title="Copy rule URL" target="_blank"
1018
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23prefer-gm-add-style">
1019
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1020
+ </h3>
1021
+
1022
+ <details>
1023
+
1024
+ <summary>Prefers <code>GM_addStyle()</code> or a shadow root over manual <code>&lt;style&gt;</code> injection.</summary>
1025
+
1026
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
1027
+
1028
+ ```diff
1029
+ ! const style = document.createElement('style')
1030
+ ! style.textContent = 'body { color: red }'
1031
+ ! document.head.append(style)
1032
+ ```
1033
+
1034
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
1035
+
1036
+ ```diff
1037
+ - const style = document.createElement('style')
1038
+ - style.textContent = 'body { color: red }'
1039
+ - document.head.append(style)
1040
+ + GM_addStyle('body { color: red }')
1041
+ ```
1042
+
1043
+ #### When not to use it
1044
+
1045
+ If you deliberately need manual control over the injected `<style>`.
1046
+
1047
+ #### Introduced in
1048
+
1049
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.9.0">v1.9.0</a> (October 18, 2026)
1050
+
1051
+ #### See also
1052
+
1053
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=tampermonkey.net&sz=64">&ensp;<a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=GM_addStyle">Tampermonkey — `GM_addStyle`</a>
1054
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=docs.scriptcat.org&sz=64">&ensp;<a target="_blank" href="https://docs.scriptcat.org/en/docs/dev/api/#gm_addstyle">ScriptCat — `GM_addStyle`</a>
1055
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM">MDN — Using shadow DOM</a>
1056
+
1057
+ <div align="center">
1058
+
1059
+ [Back to index ↑][epg-rules]
1060
+
1061
+ </div>
1062
+
1063
+ ---
1064
+
1065
+ </details>
1066
+
720
1067
  <h3 id="prefer-match">
721
1068
  <code>prefer-match</code>
722
1069
  <a title="Included in recommended config" href="#usage">
723
1070
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
724
- <a title="Copy rule URL" target="_blank"
1071
+ <a title="Included in security config" href="#usage">
1072
+ <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
1073
+ <a title="Copy rule URL" target="_blank"
725
1074
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23prefer-match">
726
1075
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
727
1076
  </h3>
@@ -778,7 +1127,7 @@ If you rely on `@include` patterns that cannot be expressed using `@match`.
778
1127
  <img height=18 alt="[Auto-fixable]" src="https://img.shields.io/badge/Auto--fixable-3b5bdb?style=flat-square" align="middle"></a>
779
1128
  <a title="Doesn't prevent bugs" href="#require-blank-line-after-meta-block">
780
1129
  <img height=18 alt="[Stylistic]" src="https://img.shields.io/badge/Stylistic-af68ff?style=flat-square" align="middle"></a>
781
- <a title="Copy rule URL" target="_blank"
1130
+ <a title="Copy rule URL" target="_blank"
782
1131
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-blank-line-after-meta-block">
783
1132
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
784
1133
  </h3>
@@ -847,7 +1196,7 @@ If you don't care about visual separation between metadata and code.
847
1196
  <img height=18 alt="[Strict only]" src="https://img.shields.io/badge/Strict_only-ff8c42?style=flat-square" align="middle"></a>
848
1197
  <a title="Accepts eslint --fix" target="_blank" href="https://eslint.org/docs/latest/use/command-line-interface#--fix">
849
1198
  <img height=18 alt="[Auto-fixable]" src="https://img.shields.io/badge/Auto--fixable-3b5bdb?style=flat-square" align="middle"></a>
850
- <a title="Copy rule URL" target="_blank"
1199
+ <a title="Copy rule URL" target="_blank"
851
1200
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-homepage-pair">
852
1201
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
853
1202
  </h3>
@@ -896,13 +1245,72 @@ If you don't care about ensuring homepage URL compatibility across different man
896
1245
 
897
1246
  </details>
898
1247
 
1248
+ <h3 id="require-license-header">
1249
+ <code>require-license-header</code>
1250
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">
1251
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1252
+ <a title="Only included in strict config" href="#usage">
1253
+ <img height=18 alt="[Strict only]" src="https://img.shields.io/badge/Strict_only-ff8c42?style=flat-square" align="middle"></a>
1254
+ <a title="Copy rule URL" target="_blank"
1255
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-license-header">
1256
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1257
+ </h3>
1258
+
1259
+ <details>
1260
+
1261
+ <summary>Requires the <code>@license</code> metadata field.</summary>
1262
+
1263
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
1264
+
1265
+ ```diff
1266
+ // ==UserScript==
1267
+ // @name My Script
1268
+ // ==/UserScript==
1269
+ ```
1270
+
1271
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
1272
+
1273
+ ```diff
1274
+ // ==UserScript==
1275
+ // @name My Script
1276
+ + // @license MIT
1277
+ // ==/UserScript==
1278
+ ```
1279
+
1280
+ #### When not to use it
1281
+
1282
+ If you don't distribute your script, or you intentionally omit a license field.
1283
+
1284
+ #### Introduced in
1285
+
1286
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">v1.10.0</a> (October 22, 2026)
1287
+
1288
+ #### See also
1289
+
1290
+ - [`valid-license-header`](#valid-license-header)
1291
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1292
+ <a title="Accepts array w/ options" href="#valid-license-header-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1293
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=docs.scriptcat.org&sz=64">&ensp;<a target="_blank" href="https://docs.scriptcat.org/en/docs/dev/meta/#license">ScriptCat — @license</a>
1294
+
1295
+ <div align="center">
1296
+
1297
+ [Back to index ↑][epg-rules]
1298
+
1299
+ </div>
1300
+
1301
+ ---
1302
+
1303
+ </details>
1304
+
899
1305
  <h3 id="require-matching-localized-fields">
900
1306
  <code>require-matching-localized-fields</code>
1307
+ <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">
1308
+ <img height=18 align="middle" src="https://api.iconify.design/ph/flag-banner-fold-fill.svg?color=%234a4a4a"></a>
901
1309
  <a title="Included in recommended config" href="#usage">
902
1310
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
903
1311
  <a title="Accepts array w/ options" href="#usage">
904
1312
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
905
- <a title="Copy rule URL" target="_blank"
1313
+ <a title="Copy rule URL" target="_blank"
906
1314
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-matching-localized-fields">
907
1315
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
908
1316
  </h3>
@@ -913,13 +1321,13 @@ If you don't care about ensuring homepage URL compatibility across different man
913
1321
 
914
1322
  <h4 id="require-matching-localized-fields-options">Options</h4>
915
1323
 
916
- - `ignoreLanguages` (default `[]`) – language code(s) to skip (e.g. `'de'` or `['es', 'fr']`)
1324
+ - `ignoreLanguages` (default `[]`) – language code(s) to skip (e.g. `'de'` or `['es', 'fr']`) – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
917
1325
 
918
1326
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
919
1327
 
920
1328
  ```diff
921
1329
  /* eslint greasemonkey/require-matching-localized-fields: ['error', { ignoreLanguages: ['fr'] }] */
922
-
1330
+
923
1331
  // ==UserScript==
924
1332
  // @name:en My Script
925
1333
  ! // @name:de Mein Skript
@@ -932,7 +1340,7 @@ If you don't care about ensuring homepage URL compatibility across different man
932
1340
 
933
1341
  ```diff
934
1342
  /* eslint greasemonkey/require-matching-localized-fields: ['error', { ignoreLanguages: ['fr'] }] */
935
-
1343
+
936
1344
  // ==UserScript==
937
1345
  // @name:en My Script
938
1346
  // @name:de Mein Skript
@@ -970,11 +1378,13 @@ If you intentionally provide localized names without descriptions (or vice versa
970
1378
 
971
1379
  <h3 id="require-required-fields">
972
1380
  <code>require-required-fields</code>
1381
+ <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">
1382
+ <img height=18 align="middle" src="https://api.iconify.design/ph/flag-banner-fold-fill.svg?color=%234a4a4a"></a>
973
1383
  <a title="Included in recommended config" href="#usage">
974
1384
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
975
1385
  <a title="Accepts array w/ options" href="#usage">
976
1386
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
977
- <a title="Copy rule URL" target="_blank"
1387
+ <a title="Copy rule URL" target="_blank"
978
1388
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-required-fields">
979
1389
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
980
1390
  </h3>
@@ -985,14 +1395,14 @@ If you intentionally provide localized names without descriptions (or vice versa
985
1395
 
986
1396
  <h4 id="require-required-fields-options">Options</h4>
987
1397
 
988
- - `fields` (default `['name', 'version']`) – override the required field list
989
- - `requireMatchOrInclude` (default `true`) – require `@match` or `@include`
1398
+ - `fields` (default `['name', 'version']`) – override the required field list – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
1399
+ - `requireMatchOrInclude` (default `true`) – require `@match` or `@include` – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
990
1400
 
991
1401
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
992
1402
 
993
1403
  ```diff
994
1404
  /* eslint greasemonkey/require-required-fields: ['error', { fields: ['name', 'version', 'license'] }] */
995
-
1405
+
996
1406
  // ==UserScript==
997
1407
  // @name My Script
998
1408
  // ==/UserScript==
@@ -1002,7 +1412,7 @@ If you intentionally provide localized names without descriptions (or vice versa
1002
1412
 
1003
1413
  ```diff
1004
1414
  /* eslint greasemonkey/require-required-fields: ['error', { fields: ['name', 'version', 'license'] }] */
1005
-
1415
+
1006
1416
  // ==UserScript==
1007
1417
  // @name My Script
1008
1418
  + // @version 1.0.0
@@ -1045,7 +1455,7 @@ If your script is a work-in-progress, or metadata is injected at build time.
1045
1455
  <img height=18 alt="[Auto-fixable]" src="https://img.shields.io/badge/Auto--fixable-3b5bdb?style=flat-square" align="middle"></a>
1046
1456
  <a title="Doesn't prevent bugs" href="#require-space-before-meta-key">
1047
1457
  <img height=18 alt="[Stylistic]" src="https://img.shields.io/badge/Stylistic-af68ff?style=flat-square" align="middle"></a>
1048
- <a title="Copy rule URL" target="_blank"
1458
+ <a title="Copy rule URL" target="_blank"
1049
1459
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-space-before-meta-key">
1050
1460
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1051
1461
  </h3>
@@ -1105,11 +1515,13 @@ If you intentionally use a different prefix style.
1105
1515
 
1106
1516
  <h3 id="require-sri-hashing">
1107
1517
  <code>require-sri-hashing</code>
1108
- <a title="Only included in strict config" href="#usage">
1109
- <img height=18 alt="[Strict only]" src="https://img.shields.io/badge/Strict_only-ff8c42?style=flat-square" align="middle"></a>
1518
+ <a title="Included in strict config" href="#usage">
1519
+ <img height=18 alt="[Strict]" src="https://img.shields.io/badge/Strict-ff8c42?style=flat-square" align="middle"></a>
1520
+ <a title="Included in security config" href="#usage">
1521
+ <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
1110
1522
  <a title="Accepts array w/ options" href="#usage">
1111
1523
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1112
- <a title="Copy rule URL" target="_blank"
1524
+ <a title="Copy rule URL" target="_blank"
1113
1525
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-sri-hashing">
1114
1526
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1115
1527
  </h3>
@@ -1120,7 +1532,7 @@ If you intentionally use a different prefix style.
1120
1532
 
1121
1533
  <h4 id="require-sri-hashing-options">Options</h4>
1122
1534
 
1123
- - `algorithm` (default `'sha256'`) – SRI hash algorithm(s) to enforce (`'md5'`, `'sha1'`, `'sha256'`, `'sha384'`, `'sha512'`), as a single string or array
1535
+ - `algorithm` (default `'sha256'`) – SRI hash algorithm(s) to enforce (`'md5'`, `'sha1'`, `'sha256'`, `'sha384'`, `'sha512'`), as a single string or array – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.5.0">v1.5.0</a>]
1124
1536
 
1125
1537
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
1126
1538
 
@@ -1158,6 +1570,9 @@ If you prefer shorter URLs, or don't support users who strictly enforce subresou
1158
1570
 
1159
1571
  #### See also
1160
1572
 
1573
+ - [`no-insecure-fetch`](#no-insecure-fetch)
1574
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1575
+ <a title="Included in security config" href="#usage"><img height=14 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
1161
1576
  - <img height=12 src="https://www.google.com/s2/favicons?domain=tampermonkey.net&sz=64">&ensp;<a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=sri">Tampermonkey — Subresource Integrity</a>
1162
1577
  - <img height=12 src="https://www.google.com/s2/favicons?domain=docs.scriptcat.org&sz=64">&ensp;<a target="_blank" href="https://docs.scriptcat.org/en/docs/dev/meta/#resource-integrity-verification">ScriptCat — Resource Integrity Verification</a>
1163
1578
 
@@ -1181,7 +1596,7 @@ If you prefer shorter URLs, or don't support users who strictly enforce subresou
1181
1596
  <img height=18 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
1182
1597
  <a title="Included in adguard config" href="#usage">
1183
1598
  <img height=18 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
1184
- <a title="Copy rule URL" target="_blank"
1599
+ <a title="Copy rule URL" target="_blank"
1185
1600
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-update-download-pair">
1186
1601
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1187
1602
  </h3>
@@ -1234,7 +1649,7 @@ If you don't strictly target Tampermonkey, ScriptCat or AdGuard (where `@updateU
1234
1649
  <code>require-user-js-filename</code>
1235
1650
  <a title="Included in recommended config" href="#usage">
1236
1651
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1237
- <a title="Copy rule URL" target="_blank"
1652
+ <a title="Copy rule URL" target="_blank"
1238
1653
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23require-user-js-filename">
1239
1654
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1240
1655
  </h3>
@@ -1276,6 +1691,8 @@ If you intentionally name your userscripts something other than `*.user.js`.
1276
1691
 
1277
1692
  <h3 id="valid-field-values">
1278
1693
  <code>valid-field-values</code>
1694
+ <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">
1695
+ <img height=18 align="middle" src="https://api.iconify.design/ph/flag-banner-fold-fill.svg?color=%234a4a4a"></a>
1279
1696
  <a title="Included in recommended config" href="#usage">
1280
1697
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1281
1698
  <a title="Accepts array w/ options" href="#usage">
@@ -1291,15 +1708,15 @@ If you intentionally name your userscripts something other than `*.user.js`.
1291
1708
 
1292
1709
  <h4 id="valid-field-values-options">Options</h4>
1293
1710
 
1294
- - `versionType` (default `'semver'`) – version format to enforce (`'semver'`, `'date'`)
1295
- - `allowFutureDate` (default `false`) – allow `@version` dates later than the current date
1296
- - `timezone` (default `''`) – <a target="_blank" href="https://data.iana.org/time-zones/tzdb/zone1970.tab">IANA timezone</a> used to determine the current date (when omitted, only year/month are enforced)
1711
+ - `versionType` (default `'semver'`) – version format to enforce (`'semver'`, `'date'`) – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
1712
+ - `allowFutureDate` (default `false`) – allow `@version` dates later than the current date – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
1713
+ - `timezone` (default `''`) – <a target="_blank" href="https://data.iana.org/time-zones/tzdb/zone1970.tab">IANA timezone</a> used to determine the current date (when omitted, only year/month are enforced) – [since <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.0.0">v1.0.0</a>]
1297
1714
 
1298
1715
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
1299
1716
 
1300
1717
  ```diff
1301
1718
  /* eslint greasemonkey/valid-field-values: ['error', { versionType: 'semver' }] */
1302
-
1719
+
1303
1720
  // ==UserScript==
1304
1721
  ! // @version abc
1305
1722
  ! // @homepage not-a-url
@@ -1310,7 +1727,7 @@ If you intentionally name your userscripts something other than `*.user.js`.
1310
1727
 
1311
1728
  ```diff
1312
1729
  /* eslint greasemonkey/valid-field-values: ['error', { versionType: 'semver' }] */
1313
-
1730
+
1314
1731
  // ==UserScript==
1315
1732
  - // @version abc
1316
1733
  + // @version 1.0.0
@@ -1332,7 +1749,7 @@ If you use a custom versioning scheme or URLs that aren't standard.
1332
1749
  - [`no-invalid-grants`](#no-invalid-grants)
1333
1750
  <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1334
1751
  <a title="Optimized in tampermonkey config" href="#usage"><img height=14 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
1335
- <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-f01e07?style=flat-square" align="middle"></a>
1752
+ <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
1336
1753
  <a title="Optimized in greasemonkey config" href="#usage"><img height=14 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
1337
1754
  <a title="Optimized in scriptcat config" href="#usage"><img height=14 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
1338
1755
  <a title="Optimized in adguard config" href="#usage"><img height=14 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
@@ -1340,11 +1757,302 @@ If you use a custom versioning scheme or URLs that aren't standard.
1340
1757
  - [`no-invalid-headers`](#no-invalid-headers)
1341
1758
  <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1342
1759
  <a title="Optimized in tampermonkey config" href="#usage"><img height=14 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
1343
- <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-f01e07?style=flat-square" align="middle"></a>
1760
+ <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
1761
+ <a title="Optimized in greasemonkey config" href="#usage"><img height=14 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
1762
+ <a title="Optimized in scriptcat config" href="#usage"><img height=14 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
1763
+ <a title="Optimized in adguard config" href="#usage"><img height=14 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
1764
+ <a title="Accepts array w/ options" href="#no-invalid-headers-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1765
+
1766
+ <div align="center">
1767
+
1768
+ [Back to index ↑][epg-rules]
1769
+
1770
+ </div>
1771
+
1772
+ ---
1773
+
1774
+ </details>
1775
+
1776
+ <h3 id="valid-icon-headers">
1777
+ <code>valid-icon-headers</code>
1778
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">
1779
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1780
+ <a title="Included in recommended config" href="#usage">
1781
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1782
+ <a title="Copy rule URL" target="_blank"
1783
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23valid-icon-headers">
1784
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1785
+ </h3>
1786
+
1787
+ <details>
1788
+
1789
+ <summary>Validates <code>@icon</code>/<code>@icon64</code>/<code>@defaulticon</code> against allowed schemes.</summary>
1790
+
1791
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
1792
+
1793
+ ```diff
1794
+ // ==UserScript==
1795
+ // @name My Script
1796
+ ! // @icon data:image/png;base64abc
1797
+ ! // @icon64 data:text/plain;base64,SGVsbG8=
1798
+ ! // @defaulticon ftp://example.com/icon.png
1799
+ // ==/UserScript==
1800
+ ```
1801
+
1802
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
1803
+
1804
+ ```diff
1805
+ // ==UserScript==
1806
+ // @name My Script
1807
+ - // @icon data:image/png;base64abc
1808
+ + // @icon data:image/png;base64,iVBORw0KGgo=
1809
+ - // @icon64 data:text/plain;base64,SGVsbG8=
1810
+ + // @icon64 data:image/png;base64,iVBORw0KGgo=
1811
+ - // @defaulticon ftp://example.com/icon.png
1812
+ + // @defaulticon https://example.com/icon.png
1813
+ // ==/UserScript==
1814
+ ```
1815
+
1816
+ #### When not to use it
1817
+
1818
+ If you intentionally use URL schemes outside `http(s)`, `data:`, and relative paths.
1819
+
1820
+ #### Introduced in
1821
+
1822
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">v1.10.0</a> (October 22, 2026)
1823
+
1824
+ #### See also
1825
+
1826
+ - [`no-invalid-headers`](#no-invalid-headers)
1827
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1828
+ <a title="Optimized in tampermonkey config" href="#usage"><img height=14 alt="[Tampermonkey]" src="https://img.shields.io/badge/Tampermonkey-00485b?style=flat-square" align="middle"></a>
1829
+ <a title="Optimized in violentmonkey config" href="#usage"><img height=14 alt="[Violentmonkey]" src="https://img.shields.io/badge/Violentmonkey-c68a3c?style=flat-square" align="middle"></a>
1344
1830
  <a title="Optimized in greasemonkey config" href="#usage"><img height=14 alt="[Greasemonkey]" src="https://img.shields.io/badge/Greasemonkey-6c4d8c?style=flat-square" align="middle"></a>
1345
1831
  <a title="Optimized in scriptcat config" href="#usage"><img height=14 alt="[ScriptCat]" src="https://img.shields.io/badge/ScriptCat-1296dc?style=flat-square" align="middle"></a>
1346
1832
  <a title="Optimized in adguard config" href="#usage"><img height=14 alt="[AdGuard]" src="https://img.shields.io/badge/AdGuard-68bd72?style=flat-square" align="middle"></a>
1347
1833
  <a title="Accepts array w/ options" href="#no-invalid-headers-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1834
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=tampermonkey.net&sz=64">&ensp;<a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=icon">Tampermonkey — `@icon`, `@icon64`</a>
1835
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/data">MDN — `data:` URLs</a>
1836
+
1837
+ <div align="center">
1838
+
1839
+ [Back to index ↑][epg-rules]
1840
+
1841
+ </div>
1842
+
1843
+ ---
1844
+
1845
+ </details>
1846
+
1847
+ <h3 id="valid-license-header">
1848
+ <code>valid-license-header</code>
1849
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">
1850
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1851
+ <a title="Included in recommended config" href="#usage">
1852
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1853
+ <a title="Accepts array w/ options" href="#usage">
1854
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1855
+ <a title="Copy rule URL" target="_blank"
1856
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23valid-license-header">
1857
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1858
+ </h3>
1859
+
1860
+ <details>
1861
+
1862
+ <summary>Validates <code>@license</code> values against the SPDX license list.</summary>
1863
+
1864
+ <h4 id="valid-license-header-options">Options</h4>
1865
+
1866
+ - `allowedLicenses` (default `[]`) – <a target="_blank" href="https://spdx.org/licenses/">SPDX license IDs</a> to restrict to (e.g. `['Apache-2.0', 'MIT']`), as a single string or array
1867
+
1868
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
1869
+
1870
+ ```diff
1871
+ // ==UserScript==
1872
+ // @name My Script
1873
+ ! // @license mit
1874
+ // ==/UserScript==
1875
+ ```
1876
+
1877
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
1878
+
1879
+ ```diff
1880
+ // ==UserScript==
1881
+ // @name My Script
1882
+ - // @license mit
1883
+ + // @license MIT
1884
+ // ==/UserScript==
1885
+ ```
1886
+
1887
+ #### When not to use it
1888
+
1889
+ If your `@license` uses a custom identifier that isn't a valid SPDX value.
1890
+
1891
+ #### Introduced in
1892
+
1893
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">v1.10.0</a> (October 22, 2026)
1894
+
1895
+ #### See also
1896
+
1897
+ - [`require-license-header`](#require-license-header)
1898
+ <a title="Only included in strict config" href="#usage"><img height=14 alt="[Strict only]" src="https://img.shields.io/badge/Strict_only-ff8c42?style=flat-square" align="middle"></a>
1899
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=spdx.org&sz=64">&ensp;<a target="_blank" href="https://spdx.org/licenses/">SPDX — License List</a>
1900
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=spdx.org&sz=64">&ensp;<a target="_blank" href="https://spdx.github.io/spdx-spec/v2.3/SPDX-license-expressions/">SPDX — License Expressions</a>
1901
+
1902
+ <div align="center">
1903
+
1904
+ [Back to index ↑][epg-rules]
1905
+
1906
+ </div>
1907
+
1908
+ ---
1909
+
1910
+ </details>
1911
+
1912
+ <h3 id="valid-url-headers">
1913
+ <code>valid-url-headers</code>
1914
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">
1915
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1916
+ <a title="Included in recommended config" href="#usage">
1917
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1918
+ <a title="Accepts array w/ options" href="#usage">
1919
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1920
+ <a title="Copy rule URL" target="_blank"
1921
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23valid-url-headers">
1922
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1923
+ </h3>
1924
+
1925
+ <details>
1926
+
1927
+ <summary>Validates URLs and match patterns in metadata headers.</summary>
1928
+
1929
+ <h4 id="valid-url-headers-options">Options</h4>
1930
+
1931
+ - `checkURLfields` (default `true`) – validate URL fields (`@homepage`, `@require`, `@require-css`, `@resource`, `@source`, `@website`, and any header ending in `url`)
1932
+ - `checkMatchPatterns` (default `true`) – validate match patterns (`@match`, `@include`, `@exclude`, `@exclude-match`)
1933
+ - `allowedSchemes` (default `['http', 'https', 'file', 'ftp', 'http*']`) – permitted URL schemes for match patterns, as a single string or array
1934
+ - `allowBroadPatterns` (default `false`) – permit unrestricted patterns (`*://*/*`, `http*://*/*`, `https://*/*`)
1935
+
1936
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
1937
+
1938
+ ```diff
1939
+ // ==UserScript==
1940
+ // @name My Script
1941
+ ! // @match *://*foo.com/*
1942
+ ! // @match https://example.com
1943
+ ! // @require not-a-valid-url
1944
+ ! // @homepageURL example.com
1945
+ ! // @resource myCSS not-a-url
1946
+ // ==/UserScript==
1947
+ ```
1948
+
1949
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
1950
+
1951
+ ```diff
1952
+ // ==UserScript==
1953
+ // @name My Script
1954
+ - // @match *://*foo.com/*
1955
+ + // @match *://*.foo.com/*
1956
+ - // @match https://example.com
1957
+ + // @match https://example.com/*
1958
+ - // @require not-a-valid-url
1959
+ + // @require https://cdn.example.com/lib.js
1960
+ - // @homepageURL example.com
1961
+ + // @homepageURL https://example.com
1962
+ - // @resource myCSS not-a-url
1963
+ + // @resource myCSS https://example.com/style.css
1964
+ // ==/UserScript==
1965
+ ```
1966
+
1967
+ #### When not to use it
1968
+
1969
+ If your URLs or patterns are generated at build time.
1970
+
1971
+ #### Introduced in
1972
+
1973
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">v1.10.0</a> (October 22, 2026)
1974
+
1975
+ #### See also
1976
+
1977
+ - [`valid-field-values`](#valid-field-values)
1978
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1979
+ <a title="Accepts array w/ options" href="#valid-field-values-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1980
+ - [`valid-icon-headers`](#valid-icon-headers)
1981
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1982
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=tampermonkey.net&sz=64">&ensp;<a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=include#meta:match">Tampermonkey — `@match`</a>
1983
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=tampermonkey.net&sz=64">&ensp;<a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=include#meta:include">Tampermonkey — `@include`</a>
1984
+
1985
+ <div align="center">
1986
+
1987
+ [Back to index ↑][epg-rules]
1988
+
1989
+ </div>
1990
+
1991
+ ---
1992
+
1993
+ </details>
1994
+
1995
+ <h3 id="valid-version-header">
1996
+ <code>valid-version-header</code>
1997
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">
1998
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1999
+ <a title="Included in recommended config" href="#usage">
2000
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
2001
+ <a title="Accepts array w/ options" href="#usage">
2002
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
2003
+ <a title="Copy rule URL" target="_blank"
2004
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-greasemonkey%2F%23valid-version-header">
2005
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
2006
+ </h3>
2007
+
2008
+ <details>
2009
+
2010
+ <summary>Validates the <code>@version</code> metadata field.</summary>
2011
+
2012
+ <h4 id="valid-version-header-options">Options</h4>
2013
+
2014
+ - `versionType` (default `'semver'`) – version format to enforce (`'semver'`, `'date'`)
2015
+ - `allowFutureDate` (default `false`) – allow `@version` dates later than the current date
2016
+ - `timezone` (default `''`) – <a target="_blank" href="https://data.iana.org/time-zones/tzdb/zone1970.tab">IANA timezone</a> used to determine the current date (when omitted, only year/month are enforced)
2017
+
2018
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
2019
+
2020
+ ```diff
2021
+ /* eslint greasemonkey/valid-version-header: ['error', { versionType: 'date' }] */
2022
+
2023
+ // ==UserScript==
2024
+ // @name My Script
2025
+ ! // @version 2026.1.111
2026
+ // ==/UserScript==
2027
+ ```
2028
+
2029
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
2030
+
2031
+ ```diff
2032
+ /* eslint greasemonkey/valid-version-header: ['error', { versionType: 'date' }] */
2033
+
2034
+ // ==UserScript==
2035
+ // @name My Script
2036
+ - // @version 2026.1.111
2037
+ + // @version 2026.10.3
2038
+ // ==/UserScript==
2039
+ ```
2040
+
2041
+ #### When not to use it
2042
+
2043
+ If you use a custom versioning scheme, or your `@version` is injected at build time.
2044
+
2045
+ #### Introduced in
2046
+
2047
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/releases/tag/v1.10.0">v1.10.0</a> (October 22, 2026)
2048
+
2049
+ #### See also
2050
+
2051
+ - [`require-required-fields`](#require-required-fields)
2052
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
2053
+ <a title="Accepts array w/ options" href="#require-required-fields-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
2054
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=tampermonkey.net&sz=64">&ensp;<a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=version">Tampermonkey — `@version`</a>
2055
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=wiki.greasespot.net&sz=64">&ensp;<a target="_blank" href="https://wiki.greasespot.net/Metadata_Block#.40version">Greasemonkey — `@version`</a>
1348
2056
 
1349
2057
  <div align="center">
1350
2058
 
@@ -1378,8 +2086,8 @@ If you use a custom versioning scheme or URLs that aren't standard.
1378
2086
 
1379
2087
  ## <img height=30 width=27 align="top" src="https://api.iconify.design/ic/baseline-account-balance.svg?color=%232b2b2a"> License
1380
2088
 
1381
- <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/src/branch/main/docs/LICENSE.md">
1382
- <img height=85 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/9e820e5d51/assets/images/logos/mit-license/red-pixelated.png"></a>
2089
+ <a href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/src/branch/main/docs/LICENSE.md">
2090
+ <img height=88 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-chrome-extensions/d79e1db7e2/assets/images/banners/mit-license/banner.png"></a>
1383
2091
  <br><br>
1384
2092
 
1385
2093
  <details>