eslint-plugin-chrome-extensions 2.4.2 → 2.6.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 (47) hide show
  1. package/README.md +272 -115
  2. package/package.json +6 -8
  3. package/src/data/apis.js +166 -115
  4. package/src/data/deprecations.js +5 -7
  5. package/src/data/i18n.js +19 -69
  6. package/src/data/manifest.js +61 -57
  7. package/src/data/permissions.js +23 -30
  8. package/src/data/regex.js +10 -0
  9. package/src/index.js +7 -124
  10. package/src/rules/manifest-key-order.js +8 -8
  11. package/src/rules/manifest-spacing.js +5 -5
  12. package/src/rules/no-content-style-leak.js +6 -4
  13. package/src/rules/no-deprecated-apis.js +4 -4
  14. package/src/rules/no-duplicate-manifest-keys.js +3 -4
  15. package/src/rules/no-insecure-messaging.js +4 -4
  16. package/src/rules/no-invalid-locales.js +89 -0
  17. package/src/rules/no-invalid-permissions.js +10 -13
  18. package/src/rules/no-missing-default-locale.js +44 -21
  19. package/src/rules/no-missing-i18n-keys.js +24 -25
  20. package/src/rules/no-missing-permissions.js +7 -6
  21. package/src/rules/no-missing-web-accessible-resources.js +7 -6
  22. package/src/rules/no-remote-code.js +12 -12
  23. package/src/rules/no-sensitive-permissions.js +75 -0
  24. package/src/rules/no-unrestricted-host-permissions.js +35 -19
  25. package/src/rules/no-unused-i18n-keys.js +11 -10
  26. package/src/rules/no-unused-permissions.js +31 -23
  27. package/src/rules/require-license-file.js +4 -5
  28. package/src/rules/require-mv3.js +5 -6
  29. package/src/rules/require-short-name-when-useful.js +4 -3
  30. package/src/rules/valid-filenames.js +3 -10
  31. package/src/rules/valid-license-file.js +18 -11
  32. package/src/rules/valid-manifest-icons.js +35 -6
  33. package/src/rules/valid-mv3-schema.js +22 -22
  34. package/src/rules/valid-service-worker.js +34 -13
  35. package/src/rules/valid-url-fields.js +49 -41
  36. package/src/rules/valid-version-field.js +5 -9
  37. package/src/utils/extension.js +52 -33
  38. package/src/utils/i18n.js +58 -0
  39. package/src/utils/init.js +107 -0
  40. package/src/utils/license.js +56 -0
  41. package/src/utils/node.js +20 -19
  42. package/src/utils/pkg.js +12 -10
  43. package/src/utils/rules.js +6 -4
  44. package/src/utils/text.js +13 -0
  45. package/src/data/license.js +0 -28
  46. package/src/data/text-parser.js +0 -11
  47. package/src/utils/bundle.js +0 -10
package/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
  <img alt="[Latest Build]" src="https://img.shields.io/npm/v/eslint-plugin-chrome-extensions?logo=icinga&style=for-the-badge&label=Latest%20Build&color=32fcee"></a>
7
7
  <a href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/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
+ <a target="_blank" href="https://getnpmstats.com/?package=eslint-plugin-chrome-extensions&range=last-year&interval=monthly">
10
+ <img src="https://img.shields.io/npm/dm/eslint-plugin-chrome-extensions?style=for-the-badge&logo=npm&color=black"></a>
9
11
  <a target="_blank" href="https://eslint.org/">
10
12
  <img alt="[Requires ESLint >=9.6.0]" src="https://img.shields.io/badge/Requires-ESLint_%3E%3D9.6.0-4B32C3?style=for-the-badge&logo=eslint"></a>
11
13
  <br><br>
@@ -84,7 +86,7 @@ Available bundles: `recommended`, `strict` (everything), `problem` (deterministi
84
86
  <img height=18 alt="[Stylistic]" src="https://img.shields.io/badge/Stylistic-af68ff?style=flat-square" align="middle"></a>
85
87
  <a title="Accepts array w/ options" href="#usage">
86
88
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
87
- <a title="Copy rule URL" target="_blank"
89
+ <a title="Copy rule URL" target="_blank"
88
90
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23manifest-key-order">
89
91
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
90
92
  </h3>
@@ -95,13 +97,13 @@ Available bundles: `recommended`, `strict` (everything), `problem` (deterministi
95
97
 
96
98
  <h4 id="manifest-key-order-options">Options</h4>
97
99
 
98
- - `order` (default `[]`) – manifest keys in custom order (e.g. `['name', 'manifest_version']`) to selectively override built-in order with
100
+ - `order` (default `[]`) – manifest keys in custom order (e.g. `['name', 'manifest_version']`) to selectively override built-in order with <a title="Introduced in v2.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.0.0"><img height=14 alt="[Since v2.0.0]" src="https://img.shields.io/badge/since-v2.0.0-8a9199?style=flat-square" align="middle"></a>
99
101
 
100
102
  #### <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
101
103
 
102
104
  ```diff
103
105
  /* eslint chrome-extensions/manifest-key-order: ['error', { order: ['name', 'manifest_version'] }] */
104
-
106
+
105
107
  {
106
108
  ! "manifest_version": 3,
107
109
  "name": "My Extension",
@@ -113,7 +115,7 @@ Available bundles: `recommended`, `strict` (everything), `problem` (deterministi
113
115
 
114
116
  ```diff
115
117
  /* eslint chrome-extensions/manifest-key-order: ['error', { order: ['name', 'manifest_version'] }] */
116
-
118
+
117
119
  {
118
120
  - "manifest_version": 3,
119
121
  "name": "My Extension",
@@ -159,7 +161,7 @@ If you don't care about the order of manifest keys.
159
161
  <img height=18 alt="[Stylistic]" src="https://img.shields.io/badge/Stylistic-af68ff?style=flat-square" align="middle"></a>
160
162
  <a title="Accepts array w/ options" href="#usage">
161
163
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
162
- <a title="Copy rule URL" target="_blank"
164
+ <a title="Copy rule URL" target="_blank"
163
165
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23manifest-spacing">
164
166
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
165
167
  </h3>
@@ -170,17 +172,17 @@ If you don't care about the order of manifest keys.
170
172
 
171
173
  <h4 id="manifest-spacing-options">Options</h4>
172
174
 
173
- - `spaces` (default `2`) – number of spaces per indent level
174
- - `checkColons` (default `true`) – enforce 0 spaces before and 1 space after `:` in key/value pairs
175
- - `checkCommas` (default `true`) – enforce 0 spaces before and 1 space after `,` in inline objects
176
- - `checkBraces` (default `true`) – enforce 1 space after `{` and before `}` in inline objects
177
- - `checkBrackets` (default `true`) – enforce 0 spaces after `[` and before `]` in inline arrays
175
+ - `spaces` (default `2`) – number of spaces per indent level <a title="Introduced in v2.2.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.2.0"><img height=14 alt="[Since v2.2.0]" src="https://img.shields.io/badge/since-v2.2.0-8a9199?style=flat-square" align="middle"></a>
176
+ - `checkColons` (default `true`) – enforce 0 spaces before and 1 space after `:` in key/value pairs <a title="Introduced in v2.2.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.2.0"><img height=14 alt="[Since v2.2.0]" src="https://img.shields.io/badge/since-v2.2.0-8a9199?style=flat-square" align="middle"></a>
177
+ - `checkCommas` (default `true`) – enforce 0 spaces before and 1 space after `,` in inline objects <a title="Introduced in v2.2.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.2.0"><img height=14 alt="[Since v2.2.0]" src="https://img.shields.io/badge/since-v2.2.0-8a9199?style=flat-square" align="middle"></a>
178
+ - `checkBraces` (default `true`) – enforce 1 space after `{` and before `}` in inline objects <a title="Introduced in v2.2.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.2.0"><img height=14 alt="[Since v2.2.0]" src="https://img.shields.io/badge/since-v2.2.0-8a9199?style=flat-square" align="middle"></a>
179
+ - `checkBrackets` (default `true`) – enforce 0 spaces after `[` and before `]` in inline arrays <a title="Introduced in v2.2.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.2.0"><img height=14 alt="[Since v2.2.0]" src="https://img.shields.io/badge/since-v2.2.0-8a9199?style=flat-square" align="middle"></a>
178
180
 
179
181
  #### <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
180
182
 
181
183
  ```diff
182
184
  /* eslint chrome-extensions/manifest-spacing: ['error', { spaces: 2 }] */
183
-
185
+
184
186
  {
185
187
  ! "manifest_version": 3,
186
188
  ! "version" : "1.0.0",
@@ -194,7 +196,7 @@ If you don't care about the order of manifest keys.
194
196
 
195
197
  ```diff
196
198
  /* eslint chrome-extensions/manifest-spacing: ['error', { spaces: 2 }] */
197
-
199
+
198
200
  {
199
201
  - "manifest_version": 3,
200
202
  + "manifest_version": 3,
@@ -240,7 +242,7 @@ If you don't care about visual consistency in your manifest.
240
242
  <code>no-content-style-leak</code>
241
243
  <a title="Only included in strict config" href="#usage">
242
244
  <img height=18 alt="[Strict only]" src="https://img.shields.io/badge/Strict_only-ff8c42?style=flat-square" align="middle"></a>
243
- <a title="Copy rule URL" target="_blank"
245
+ <a title="Copy rule URL" target="_blank"
244
246
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-content-style-leak">
245
247
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
246
248
  </h3>
@@ -294,7 +296,7 @@ If you intentionally interact w/ host page styles.
294
296
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
295
297
  <a title="Accepts array w/ options" href="#usage">
296
298
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
297
- <a title="Copy rule URL" target="_blank"
299
+ <a title="Copy rule URL" target="_blank"
298
300
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-deprecated-apis">
299
301
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
300
302
  </h3>
@@ -305,14 +307,14 @@ If you intentionally interact w/ host page styles.
305
307
 
306
308
  <h4 id="no-deprecated-apis-options">Options</h4>
307
309
 
308
- - `target` (default `'mv3'`) – Chrome extension manifest version whose deprecations to validate against (`'mv3'`, `'mv2'`)
309
- - `allowedAPIs` (default `[]`) – additional deprecated API namespaces to allow, as a single string or array
310
+ - `target` (default `'mv3'`) – Chrome extension manifest version whose deprecations to validate against (`'mv3'`, `'mv2'`) <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-6b8e6b?style=flat-square&labelColor=464646" align="middle"></a>
311
+ - `allowedAPIs` (default `[]`) – additional deprecated API namespaces to allow, as a single string or array <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-6b8e6b?style=flat-square&labelColor=464646" align="middle"></a>
310
312
 
311
313
  #### <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
312
314
 
313
315
  ```diff
314
316
  /* eslint chrome-extensions/no-deprecated-apis: ['error', { target: 'mv3' }] */
315
-
317
+
316
318
  ! chrome.pageAction.show(tabId)
317
319
  ! chrome.extension.getBackgroundPage().doThing()
318
320
  ! chrome.tabs.executeScript(tabId, { code: 'doThing()' })
@@ -357,7 +359,7 @@ If you don't want deprecation validation at all. For individual deprecated APIs
357
359
  <code>no-duplicate-manifest-keys</code>
358
360
  <a title="Only works in 'json/json' config block" href="#usage">
359
361
  <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
360
- <a title="Copy rule URL" target="_blank"
362
+ <a title="Copy rule URL" target="_blank"
361
363
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-duplicate-manifest-keys">
362
364
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
363
365
  </h3>
@@ -407,7 +409,8 @@ If you rely on a Chromium fork resolving duplicate keys in a specific order.
407
409
  <a title="Doesn't prevent bugs" href="#manifest-key-order"><img height=14 alt="[Stylistic]" src="https://img.shields.io/badge/Stylistic-af68ff?style=flat-square" align="middle"></a>
408
410
  <a title="Accepts array w/ options" href="#manifest-key-order-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
409
411
  - [`no-unused-permissions`](#no-unused-permissions)
410
- <a title="Only works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
412
+ <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>
413
+ <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
411
414
 
412
415
  <div align="center">
413
416
 
@@ -425,7 +428,7 @@ If you rely on a Chromium fork resolving duplicate keys in a specific order.
425
428
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
426
429
  <a title="Included in security config" href="#usage">
427
430
  <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
428
- <a title="Copy rule URL" target="_blank"
431
+ <a title="Copy rule URL" target="_blank"
429
432
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-insecure-fetch">
430
433
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
431
434
  </h3>
@@ -480,7 +483,7 @@ If you intentionally target HTTP endpoints.
480
483
  <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
481
484
  <a title="Accepts array w/ options" href="#usage">
482
485
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
483
- <a title="Copy rule URL" target="_blank"
486
+ <a title="Copy rule URL" target="_blank"
484
487
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-insecure-messaging">
485
488
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
486
489
  </h3>
@@ -491,7 +494,7 @@ If you intentionally target HTTP endpoints.
491
494
 
492
495
  <h4 id="no-insecure-messaging-options">Options</h4>
493
496
 
494
- - `disallowWildcardTarget` (default `true`) – flag <code>postMessage()</code> calls that use <code>'*'</code> as <code>targetOrigin</code>
497
+ - `disallowWildcardTarget` (default `true`) – flag <code>postMessage()</code> calls that use <code>'*'</code> as <code>targetOrigin</code> <a title="Introduced in v2.1.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.1.0"><img height=14 alt="[Since v2.1.0]" src="https://img.shields.io/badge/since-v2.1.0-8a9199?style=flat-square" align="middle"></a>
495
498
 
496
499
  #### <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
497
500
 
@@ -557,6 +560,79 @@ If you trust every external caller and open tab, or you intentionally broadcast
557
560
 
558
561
  </details>
559
562
 
563
+ <h3 id="no-invalid-locales">
564
+ <code>no-invalid-locales</code>
565
+ <a title="Included in recommended config" href="#usage">
566
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
567
+ <a title="Works in 'json/json' config block" href="#usage">
568
+ <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
569
+ <a title="Accepts array w/ options" href="#usage">
570
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
571
+ <a title="Copy rule URL" target="_blank"
572
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-invalid-locales">
573
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
574
+ </h3>
575
+
576
+ <details>
577
+
578
+ <summary>Disallows invalid Chrome locale codes in <code>_locales/</code> folders and <code>default_locale</code>.</summary>
579
+
580
+ <h4 id="no-invalid-locales-options">Options</h4>
581
+
582
+ - `allowedLocales` (default `[]`) – additional locale codes to allow, as a single string or array <a title="Introduced in v2.6.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.6.0"><img height=14 alt="[Since v2.6.0]" src="https://img.shields.io/badge/since-v2.6.0-8a9199?style=flat-square" align="middle"></a>
583
+
584
+ #### <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
585
+
586
+ ```diff
587
+ // manifest.json
588
+ {
589
+ "manifest_version": 3,
590
+ ! "default_locale": "pt-BR"
591
+ }
592
+
593
+ ! // _locales/pt-BR/messages.json
594
+ ```
595
+
596
+ #### <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
597
+
598
+ ```diff
599
+ // manifest.json
600
+ {
601
+ "manifest_version": 3,
602
+ - "default_locale": "pt-BR"
603
+ + "default_locale": "pt_BR"
604
+ }
605
+
606
+ - // _locales/pt-BR/messages.json
607
+ + // _locales/pt_BR/messages.json
608
+ ```
609
+
610
+ #### When not to use it
611
+
612
+ If your `_locales/` is externally populated at build time. If you target a Chromium fork w/ additional supported locales, prefer `allowedLocales` over disabling the rule.
613
+
614
+ #### Introduced in
615
+
616
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.6.0">v2.6.0</a> (October 16, 2026)
617
+
618
+ #### See also
619
+
620
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64">&ensp;<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/api/i18n">Chrome for Developers — `i18n`</a>
621
+ - [`no-missing-default-locale`](#no-missing-default-locale)
622
+ <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>
623
+ <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
624
+ <a title="Accepts array w/ options" href="#no-missing-default-locale-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
625
+
626
+ <div align="center">
627
+
628
+ [Back to index ↑][epce-rules]
629
+
630
+ </div>
631
+
632
+ ---
633
+
634
+ </details>
635
+
560
636
  <h3 id="no-invalid-permissions">
561
637
  <code>no-invalid-permissions</code>
562
638
  <a title="Included in recommended config" href="#usage">
@@ -565,7 +641,7 @@ If you trust every external caller and open tab, or you intentionally broadcast
565
641
  <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
566
642
  <a title="Accepts array w/ options" href="#usage">
567
643
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
568
- <a title="Copy rule URL" target="_blank"
644
+ <a title="Copy rule URL" target="_blank"
569
645
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-invalid-permissions">
570
646
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
571
647
  </h3>
@@ -576,14 +652,14 @@ If you trust every external caller and open tab, or you intentionally broadcast
576
652
 
577
653
  <h4 id="no-invalid-permissions-options">Options</h4>
578
654
 
579
- - `target` (default `'mv3'`) – Chrome manifest version whose permissions to validate against (`'mv3'`, `'mv2'`)
580
- - `allowedPermissions` (default `[]`) – additional permission names to allow beyond the built-in list, as a single string or array
655
+ - `target` (default `'mv3'`) – Chrome manifest version whose permissions to validate against (`'mv3'`, `'mv2'`) <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-6b8e6b?style=flat-square&labelColor=464646" align="middle"></a>
656
+ - `allowedPermissions` (default `[]`) – additional permission names to allow beyond the built-in list, as a single string or array <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-6b8e6b?style=flat-square&labelColor=464646" align="middle"></a>
581
657
 
582
658
  #### <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
583
659
 
584
660
  ```diff
585
661
  /* eslint chrome-extensions/no-invalid-permissions: ['error', { target: 'mv3' }] */
586
-
662
+
587
663
  {
588
664
  ! "permissions": ["browserAction", "tabs"],
589
665
  ! "optional_permissions": ["history", "pageAction"]
@@ -594,7 +670,7 @@ If you trust every external caller and open tab, or you intentionally broadcast
594
670
 
595
671
  ```diff
596
672
  /* eslint chrome-extensions/no-invalid-permissions: ['error', { target: 'mv3' }] */
597
-
673
+
598
674
  {
599
675
  - "permissions": ["browserAction", "tabs"],
600
676
  + "permissions": ["tabs"],
@@ -616,7 +692,8 @@ If you don't want permission validation at all. For custom permissions from a Ch
616
692
  - [`no-missing-permissions`](#no-missing-permissions)
617
693
  <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>
618
694
  - [`no-unused-permissions`](#no-unused-permissions)
619
- <a title="Only works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
695
+ <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>
696
+ <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
620
697
 
621
698
  <div align="center">
622
699
 
@@ -630,11 +707,13 @@ If you don't want permission validation at all. For custom permissions from a Ch
630
707
 
631
708
  <h3 id="no-missing-default-locale">
632
709
  <code>no-missing-default-locale</code>
633
- <a title="Only works in 'json/json' config block" href="#usage">
634
- <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
710
+ <a title="Included in recommended config" href="#usage">
711
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
712
+ <a title="Works in 'json/json' config block" href="#usage">
713
+ <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
635
714
  <a title="Accepts array w/ options" href="#usage">
636
715
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
637
- <a title="Copy rule URL" target="_blank"
716
+ <a title="Copy rule URL" target="_blank"
638
717
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-missing-default-locale">
639
718
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
640
719
  </h3>
@@ -645,7 +724,8 @@ If you don't want permission validation at all. For custom permissions from a Ch
645
724
 
646
725
  <h4 id="no-missing-default-locale-options">Options</h4>
647
726
 
648
- - `ignoreKeys` (default `[]`) – keys to skip when checking the default locale
727
+ - `ignoreKeys` (default `[]`) – keys to skip when checking locales <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
728
+ - `checkAllLocales` (default `false`) – also flag keys missing from any locale <a title="Introduced in v2.6.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.6.0"><img height=14 alt="[Since v2.6.0]" src="https://img.shields.io/badge/since-v2.6.0-8a9199?style=flat-square" align="middle"></a>
649
729
 
650
730
  #### <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
651
731
 
@@ -723,17 +803,9 @@ If your `_locales/` is externally populated at build time.
723
803
  <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
724
804
  <a title="Works in 'css/css' config block" href="#usage">
725
805
  <img height=18 alt="[CSS]" src="https://img.shields.io/badge/CSS-dcd6f7?style=flat-square" align="middle"></a>
726
- <a title="Works in 'html/html' config block" href="#usage">
727
- <img height=18 alt="[HTML]" src="https://img.shields.io/badge/HTML-a8d8ea?style=flat-square" align="middle"></a>
728
- <a title="Works in 'json/json' config block" href="#usage">
729
- <img height=18 alt="[JSON]" src="https://img.shields.io/badge/JSON-a8e6cf?style=flat-square" align="middle"></a>
730
- <a title="Works in 'json/json5' config block" href="#usage">
731
- <img height=18 alt="[JSON5]" src="https://img.shields.io/badge/JSON5-c7e6b8?style=flat-square" align="middle"></a>
732
- <a title="Works in 'json/jsonc' config block" href="#usage">
733
- <img height=18 alt="[JSONC]" src="https://img.shields.io/badge/JSONC-e6e6a8?style=flat-square" align="middle"></a>
734
806
  <a title="Accepts array w/ options" href="#usage">
735
807
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
736
- <a title="Copy rule URL" target="_blank"
808
+ <a title="Copy rule URL" target="_blank"
737
809
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-missing-i18n-keys">
738
810
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
739
811
  </h3>
@@ -744,7 +816,7 @@ If your `_locales/` is externally populated at build time.
744
816
 
745
817
  <h4 id="no-missing-i18n-keys-options">Options</h4>
746
818
 
747
- - `ignoreKeys` (default `[]`) – keys to skip (e.g. `['customKey']`)
819
+ - `ignoreKeys` (default `[]`) – keys to skip (e.g. `['customKey']`) <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
748
820
 
749
821
  #### <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
750
822
 
@@ -811,7 +883,7 @@ If your `_locales/` is externally populated at build time.
811
883
  <code>no-missing-permissions</code>
812
884
  <a title="Included in recommended config" href="#usage">
813
885
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
814
- <a title="Copy rule URL" target="_blank"
886
+ <a title="Copy rule URL" target="_blank"
815
887
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-missing-permissions">
816
888
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
817
889
  </h3>
@@ -862,7 +934,8 @@ If you use APIs through aliases or wrappers that obscure the original call site.
862
934
  <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
863
935
  <a title="Accepts array w/ options" href="#no-invalid-permissions-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
864
936
  - [`no-unused-permissions`](#no-unused-permissions)
865
- <a title="Only works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
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>
938
+ <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
866
939
 
867
940
  <div align="center">
868
941
 
@@ -878,7 +951,7 @@ If you use APIs through aliases or wrappers that obscure the original call site.
878
951
  <code>no-missing-web-accessible-resources</code>
879
952
  <a title="Included in recommended config" href="#usage">
880
953
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
881
- <a title="Copy rule URL" target="_blank"
954
+ <a title="Copy rule URL" target="_blank"
882
955
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-missing-web-accessible-resources">
883
956
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
884
957
  </h3>
@@ -945,7 +1018,7 @@ If your paths are built at runtime.
945
1018
  <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
946
1019
  <a title="Accepts array w/ options" href="#usage">
947
1020
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
948
- <a title="Copy rule URL" target="_blank"
1021
+ <a title="Copy rule URL" target="_blank"
949
1022
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-remote-code">
950
1023
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
951
1024
  </h3>
@@ -956,8 +1029,8 @@ If your paths are built at runtime.
956
1029
 
957
1030
  <h4 id="no-remote-code-options">Options</h4>
958
1031
 
959
- - `patterns` (default `['eval', 'new-function', 'string-timer', 'dynamic-import', 'remote-script-src', 'execute-script-url']`) – detection paths to enable, as a single string or array
960
- - `checkExecuteScriptClosures` (default `true`) – additionally flag <code>chrome.scripting.executeScript({ func })</code> bodies that capture outer-scope variables
1032
+ - `patterns` (default `['eval', 'new-function', 'string-timer', 'dynamic-import', 'remote-script-src', 'execute-script-url']`) – detection paths to enable, as a single string or array <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-6b8e6b?style=flat-square&labelColor=464646" align="middle"></a>
1033
+ - `checkExecuteScriptClosures` (default `true`) – additionally flag <code>chrome.scripting.executeScript({ func })</code> bodies that capture outer-scope variables <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-6b8e6b?style=flat-square&labelColor=464646" align="middle"></a>
961
1034
 
962
1035
  #### <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
963
1036
 
@@ -1008,13 +1081,88 @@ If you intentionally target forks w/ relaxed CSPs. For individual patterns you s
1008
1081
 
1009
1082
  </details>
1010
1083
 
1084
+ <h3 id="no-sensitive-permissions">
1085
+ <code>no-sensitive-permissions</code>
1086
+ <a title="Included in recommended config" href="#usage">
1087
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1088
+ <a title="Included in security config" href="#usage">
1089
+ <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
1090
+ <a title="Works in 'json/json' config block" href="#usage">
1091
+ <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1092
+ <a title="Accepts array w/ options" href="#usage">
1093
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1094
+ <a title="Copy rule URL" target="_blank"
1095
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-sensitive-permissions">
1096
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1097
+ </h3>
1098
+
1099
+ <details>
1100
+
1101
+ <summary>Flags sensitive manifest permissions.</summary>
1102
+
1103
+ <h4 id="no-sensitive-permissions-options">Options</h4>
1104
+
1105
+ - `allowedPermissions` (default `[]`) – sensitive permission names to explicitly allow, as a single string or array <a title="Introduced in v2.5.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.5.0"><img height=14 alt="[Since v2.5.0]" src="https://img.shields.io/badge/since-v2.5.0-8a9199?style=flat-square" align="middle"></a>
1106
+
1107
+ #### <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
1108
+
1109
+ ```diff
1110
+ {
1111
+ "manifest_version": 3,
1112
+ ! "permissions": ["tabs", "cookies", "storage"]
1113
+ }
1114
+ ```
1115
+
1116
+ #### <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
1117
+
1118
+ ```diff
1119
+ {
1120
+ "manifest_version": 3,
1121
+ - "permissions": ["tabs", "cookies", "storage"]
1122
+ + "permissions": ["storage"]
1123
+ }
1124
+ ```
1125
+
1126
+ #### When not to use it
1127
+
1128
+ If you legitimately require sensitive permissions, or prefer manual security review.
1129
+
1130
+ #### Introduced in
1131
+
1132
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.5.0">v2.5.0</a> (October 15, 2026)
1133
+
1134
+ #### See also
1135
+
1136
+ - [`no-invalid-permissions`](#no-invalid-permissions)
1137
+ <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>
1138
+ <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1139
+ <a title="Accepts array w/ options" href="#no-invalid-permissions-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1140
+ - [`no-unused-permissions`](#no-unused-permissions)
1141
+ <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>
1142
+ <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1143
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64">&ensp;<a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions">Chrome for Developers — Declare permissions</a>
1144
+
1145
+ <div align="center">
1146
+
1147
+ [Back to index ↑][epce-rules]
1148
+
1149
+ </div>
1150
+
1151
+ ---
1152
+
1153
+ </details>
1154
+
1011
1155
  <h3 id="no-unrestricted-host-permissions">
1012
1156
  <code>no-unrestricted-host-permissions</code>
1013
- <a title="Only works in 'json/json' config block" href="#usage">
1014
- <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
1157
+ <a title="Included in recommended config" href="#usage">
1158
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1159
+ <a title="Included in security config" href="#usage">
1160
+ <img height=18 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
1161
+ <a title="Works in 'json/json' config block" href="#usage">
1162
+ <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1015
1163
  <a title="Accepts array w/ options" href="#usage">
1016
1164
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1017
- <a title="Copy rule URL" target="_blank"
1165
+ <a title="Copy rule URL" target="_blank"
1018
1166
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-unrestricted-host-permissions">
1019
1167
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1020
1168
  </h3>
@@ -1025,7 +1173,7 @@ If you intentionally target forks w/ relaxed CSPs. For individual patterns you s
1025
1173
 
1026
1174
  <h4 id="no-unrestricted-host-permissions-options">Options</h4>
1027
1175
 
1028
- - `allowedPatterns` (default `[]`) – host patterns to explicitly allow (e.g. `['<all_urls>']`)
1176
+ - `allowedPatterns` (default `[]`) – host patterns to explicitly allow (e.g. `['<all_urls>']`) <a title="Introduced in v2.1.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.1.0"><img height=14 alt="[Since v2.1.0]" src="https://img.shields.io/badge/since-v2.1.0-8a9199?style=flat-square" align="middle"></a>
1029
1177
 
1030
1178
  #### <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
1031
1179
 
@@ -1078,7 +1226,7 @@ If you legitimately need broad access (e.g. ad blockers or dev tools).
1078
1226
  <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
1079
1227
  <a title="Accepts array w/ options" href="#usage">
1080
1228
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1081
- <a title="Copy rule URL" target="_blank"
1229
+ <a title="Copy rule URL" target="_blank"
1082
1230
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-unused-i18n-keys">
1083
1231
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1084
1232
  </h3>
@@ -1089,8 +1237,8 @@ If you legitimately need broad access (e.g. ad blockers or dev tools).
1089
1237
 
1090
1238
  <h4 id="no-unused-i18n-keys-options">Options</h4>
1091
1239
 
1092
- - `ignoreKeys` (default `[]`) – keys to always treat as used (e.g. `['customKey']`)
1093
- - `scanExtensions` (default `['cjs', 'css', 'htm', 'html', 'js', 'json', 'jsx', 'md', 'mjs', 'svg', 'ts', 'tsx', 'txt']`) – file extensions to scan for references
1240
+ - `ignoreKeys` (default `[]`) – keys to always treat as used (e.g. `['customKey']`) <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1241
+ - `scanExtensions` (default `['cjs', 'css', 'htm', 'html', 'js', 'json', 'jsx', 'md', 'mjs', 'svg', 'ts', 'tsx', 'txt']`) – file extensions to scan for references <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1094
1242
 
1095
1243
  #### <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
1096
1244
 
@@ -1132,10 +1280,6 @@ If your i18n keys are referenced dynamically.
1132
1280
  <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>
1133
1281
  <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1134
1282
  <a title="Works in 'css/css' config block" href="#usage"><img height=14 alt="[CSS]" src="https://img.shields.io/badge/CSS-dcd6f7?style=flat-square" align="middle"></a>
1135
- <a title="Works in 'html/html' config block" href="#usage"><img height=14 alt="[HTML]" src="https://img.shields.io/badge/HTML-a8d8ea?style=flat-square" align="middle"></a>
1136
- <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[JSON]" src="https://img.shields.io/badge/JSON-a8e6cf?style=flat-square" align="middle"></a>
1137
- <a title="Works in 'json/json5' config block" href="#usage"><img height=14 alt="[JSON5]" src="https://img.shields.io/badge/JSON5-c7e6b8?style=flat-square" align="middle"></a>
1138
- <a title="Works in 'json/jsonc' config block" href="#usage"><img height=14 alt="[JSONC]" src="https://img.shields.io/badge/JSONC-e6e6a8?style=flat-square" align="middle"></a>
1139
1283
  <a title="Accepts array w/ options" href="#no-missing-i18n-keys-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1140
1284
  - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64">&ensp;<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/api/i18n">Chrome for Developers — `i18n`</a>
1141
1285
 
@@ -1151,9 +1295,11 @@ If your i18n keys are referenced dynamically.
1151
1295
 
1152
1296
  <h3 id="no-unused-permissions">
1153
1297
  <code>no-unused-permissions</code>
1154
- <a title="Only works in 'json/json' config block" href="#usage">
1155
- <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
1156
- <a title="Copy rule URL" target="_blank"
1298
+ <a title="Included in recommended config" href="#usage">
1299
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1300
+ <a title="Works in 'json/json' config block" href="#usage">
1301
+ <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1302
+ <a title="Copy rule URL" target="_blank"
1157
1303
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-unused-permissions">
1158
1304
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1159
1305
  </h3>
@@ -1218,14 +1364,14 @@ If you access the granted API through an alias or computed property rather than
1218
1364
  <code>require-license-file</code>
1219
1365
  <a title="Only works in 'json/json' config block" href="#usage">
1220
1366
  <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
1221
- <a title="Copy rule URL" target="_blank"
1367
+ <a title="Copy rule URL" target="_blank"
1222
1368
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23require-license-file">
1223
1369
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1224
1370
  </h3>
1225
1371
 
1226
1372
  <details>
1227
1373
 
1228
- <summary>Requires a license file in the extension.</summary>
1374
+ <summary>Requires a license file.</summary>
1229
1375
 
1230
1376
  #### <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 directory structure
1231
1377
 
@@ -1238,7 +1384,7 @@ If you access the granted API through an alias or computed property rather than
1238
1384
 
1239
1385
  ```diff
1240
1386
  /extension/manifest.json
1241
- + /extension/LICENSE.md
1387
+ + /LICENSE.md
1242
1388
  ```
1243
1389
 
1244
1390
  #### When not to use it
@@ -1253,6 +1399,7 @@ If you intentionally omit a license, or it's injected at build time.
1253
1399
 
1254
1400
  - [`valid-license-file`](#valid-license-file)
1255
1401
  <a title="Only works in license config block" href="#usage"><img height=14 alt="[License only]" src="https://img.shields.io/badge/License_only-559bff?style=flat-square" align="middle"></a>
1402
+ <a title="Accepts eslint --fix" target="_blank" href="https://eslint.org/docs/latest/use/command-line-interface#--fix"><img height=14 alt="[Auto-fixable]" src="https://img.shields.io/badge/Auto--fixable-3b5bdb?style=flat-square" align="middle"></a>
1256
1403
  <a title="Accepts array w/ options" href="#valid-license-file-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1257
1404
 
1258
1405
  <div align="center">
@@ -1271,7 +1418,7 @@ If you intentionally omit a license, or it's injected at build time.
1271
1418
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1272
1419
  <a title="Works in 'json/json' config block" href="#usage">
1273
1420
  <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1274
- <a title="Copy rule URL" target="_blank"
1421
+ <a title="Copy rule URL" target="_blank"
1275
1422
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23require-mv3">
1276
1423
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1277
1424
  </h3>
@@ -1331,7 +1478,7 @@ If you intentionally target MV2 for a browser that still supports it (e.g. Firef
1331
1478
  <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
1332
1479
  <a title="Accepts array w/ options" href="#usage">
1333
1480
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1334
- <a title="Copy rule URL" target="_blank"
1481
+ <a title="Copy rule URL" target="_blank"
1335
1482
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23require-short-name-when-useful">
1336
1483
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1337
1484
  </h3>
@@ -1342,9 +1489,9 @@ If you intentionally target MV2 for a browser that still supports it (e.g. Firef
1342
1489
 
1343
1490
  <h4 id="require-short-name-when-useful-options">Options</h4>
1344
1491
 
1345
- - `maxNameLength` (default `12`) – length of `name` above which `short_name` is required
1346
- - `always` (default `false`) – require `short_name` regardless of `name` length
1347
- - `checkRedundant` (default `false`) – also flag `short_name` that duplicates `name`
1492
+ - `maxNameLength` (default `12`) – length of `name` above which `short_name` is required <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1493
+ - `always` (default `false`) – require `short_name` regardless of `name` length <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1494
+ - `checkRedundant` (default `false`) – also flag `short_name` that duplicates `name` <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1348
1495
 
1349
1496
  #### <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
1350
1497
 
@@ -1357,7 +1504,7 @@ If you intentionally target MV2 for a browser that still supports it (e.g. Firef
1357
1504
 
1358
1505
  #### <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
1359
1506
 
1360
- ```diff
1507
+ ```diff
1361
1508
  {
1362
1509
  "manifest_version": 3,
1363
1510
  "name": "Extension Infinity",
@@ -1406,7 +1553,7 @@ If you primarily target a browser that doesn't support `short_name`.
1406
1553
  <img height=18 alt="[JSONC]" src="https://img.shields.io/badge/JSONC-e6e6a8?style=flat-square" align="middle"></a>
1407
1554
  <a title="Accepts array w/ options" href="#usage">
1408
1555
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1409
- <a title="Copy rule URL" target="_blank"
1556
+ <a title="Copy rule URL" target="_blank"
1410
1557
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-filenames">
1411
1558
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1412
1559
  </h3>
@@ -1417,17 +1564,16 @@ If you primarily target a browser that doesn't support `short_name`.
1417
1564
 
1418
1565
  <h4 id="valid-filenames-options">Options</h4>
1419
1566
 
1420
- - `noReservedPrefix` (default `true`) – disallow filenames/dirs starting w/ `_` (except `_locales`)
1421
- - `noSpecialChars` (default `true`) – warn on chars outside `a-z`, `0-9`, `-`, `_`, `.`
1422
- - `checkFileExists` (default `true`) – verify files referenced in `manifest.json` actually exist
1423
- - `enforceCaseSensitivity` (default `true`) – verify manifest references match actual file case
1424
- - `maxFullPathLength` (default `260`) – max full path char length
1567
+ - `noReservedPrefix` (default `true`) – disallow filenames/dirs starting w/ `_` (except `_locales`) <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1568
+ - `noSpecialChars` (default `true`) – warn on chars outside `a-z`, `0-9`, `-`, `_`, `.` <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1569
+ - `checkFileExists` (default `true`) – verify files referenced in `manifest.json` actually exist <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1570
+ - `enforceCaseSensitivity` (default `true`) – verify manifest references match actual file case <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1571
+ - `maxFullPathLength` (default `260`) – max full path char length <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1425
1572
 
1426
- #### <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
1573
+ #### <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 names/paths
1427
1574
 
1428
1575
  ```diff
1429
- // files
1430
- ! /extension/_metadata/app.json
1576
+ ! /extension/_metadata/extension.json
1431
1577
  ! /extension/content script.js
1432
1578
 
1433
1579
  // manifest.json
@@ -1437,11 +1583,11 @@ If you primarily target a browser that doesn't support `short_name`.
1437
1583
  }
1438
1584
  ```
1439
1585
 
1440
- #### <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
1586
+ #### <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 names/paths
1441
1587
 
1442
1588
  ```diff
1443
- - /extension/_metadata/app.json
1444
- + /extension/metadata/app.json
1589
+ - /extension/_metadata/extension.json
1590
+ + /extension/metadata/extension.json
1445
1591
  - /extension/content script.js
1446
1592
  + /extension/content-script.js
1447
1593
 
@@ -1467,7 +1613,8 @@ If you don't use conventional filenames or paths, or they're generated at build
1467
1613
  - [`no-missing-web-accessible-resources`](#no-missing-web-accessible-resources)
1468
1614
  <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>
1469
1615
  - [`valid-manifest-icons`](#valid-manifest-icons)
1470
- <a title="Only works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
1616
+ <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>
1617
+ <a title="Works in 'json/json' config block" href="#usage"><img height=14 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1471
1618
  <a title="Accepts array w/ options" href="#valid-manifest-icons-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1472
1619
 
1473
1620
  <div align="center">
@@ -1484,21 +1631,23 @@ If you don't use conventional filenames or paths, or they're generated at build
1484
1631
  <code>valid-license-file</code>
1485
1632
  <a title="Only works in license config block" href="#usage">
1486
1633
  <img height=18 alt="[License only]" src="https://img.shields.io/badge/License_only-559bff?style=flat-square" align="middle"></a>
1634
+ <a title="Accepts eslint --fix" target="_blank" href="https://eslint.org/docs/latest/use/command-line-interface#--fix">
1635
+ <img height=18 alt="[Auto-fixable]" src="https://img.shields.io/badge/Auto--fixable-3b5bdb?style=flat-square" align="middle"></a>
1487
1636
  <a title="Accepts array w/ options" href="#usage">
1488
1637
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1489
- <a title="Copy rule URL" target="_blank"
1638
+ <a title="Copy rule URL" target="_blank"
1490
1639
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-license-file">
1491
1640
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1492
1641
  </h3>
1493
1642
 
1494
1643
  <details>
1495
1644
 
1496
- <summary>Validates SPDX identifiers in license files.</summary>
1645
+ <summary>Validates SPDX identifiers in license files (for compliance scanners + SBOM generators + CI gates).</summary>
1497
1646
 
1498
1647
  <h4 id="valid-license-file-options">Options</h4>
1499
1648
 
1500
- - `requireSPDX` (default `false`) – require <a target="_blank" href="https://spdx.dev/learn/handling-license-info/">`SPDX-License-Identifier`</a> in the license
1501
- - `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
1649
+ - `requireSPDX` (default `false`) – require <a target="_blank" href="https://spdx.dev/learn/handling-license-info/">`SPDX-License-Identifier`</a> in the license <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1650
+ - `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 <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1502
1651
 
1503
1652
  #### <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
1504
1653
 
@@ -1522,13 +1671,9 @@ If you don't use conventional filenames or paths, or they're generated at build
1522
1671
  + SPDX-License-Identifier: MIT
1523
1672
  ```
1524
1673
 
1525
- #### Benefits
1526
-
1527
- Makes the license machine-readable by compliance scanners + SBOM generators + CI gates.
1528
-
1529
1674
  #### When not to use it
1530
1675
 
1531
- If your license is injected at build time, or you use a license w/ no SPDX identifier.
1676
+ If your license is injected at build time, or you use one w/ no existing SPDX identifier.
1532
1677
 
1533
1678
  #### Introduced in
1534
1679
 
@@ -1552,11 +1697,13 @@ If your license is injected at build time, or you use a license w/ no SPDX ident
1552
1697
 
1553
1698
  <h3 id="valid-manifest-icons">
1554
1699
  <code>valid-manifest-icons</code>
1555
- <a title="Only works in 'json/json' config block" href="#usage">
1556
- <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
1700
+ <a title="Included in recommended config" href="#usage">
1701
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1702
+ <a title="Works in 'json/json' config block" href="#usage">
1703
+ <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1557
1704
  <a title="Accepts array w/ options" href="#usage">
1558
1705
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1559
- <a title="Copy rule URL" target="_blank"
1706
+ <a title="Copy rule URL" target="_blank"
1560
1707
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-manifest-icons">
1561
1708
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1562
1709
  </h3>
@@ -1567,9 +1714,9 @@ If your license is injected at build time, or you use a license w/ no SPDX ident
1567
1714
 
1568
1715
  <h4 id="valid-manifest-icons-options">Options</h4>
1569
1716
 
1570
- - `requireRecommendedSizes` (default `true`) – require all of `16`, `32`, `48`, `128`
1571
- - `checkIconExists` (default `true`) – flag icon paths that don't resolve to an existing file
1572
- - `noSVG` (default `true`) – flag SVG icon paths (unsupported by Chrome)
1717
+ - `requireRecommendedSizes` (default `true`) – require all of `16`, `32`, `48`, `128` <a title="Introduced in v2.1.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.1.0"><img height=14 alt="[Since v2.1.0]" src="https://img.shields.io/badge/since-v2.1.0-8a9199?style=flat-square" align="middle"></a>
1718
+ - `checkIconExists` (default `true`) – flag icon paths that don't resolve to an existing file <a title="Introduced in v2.1.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.1.0"><img height=14 alt="[Since v2.1.0]" src="https://img.shields.io/badge/since-v2.1.0-8a9199?style=flat-square" align="middle"></a>
1719
+ - `noSVG` (default `true`) – flag SVG icon paths (unsupported by Chrome) <a title="Introduced in v2.1.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.1.0"><img height=14 alt="[Since v2.1.0]" src="https://img.shields.io/badge/since-v2.1.0-8a9199?style=flat-square" align="middle"></a>
1573
1720
 
1574
1721
  #### <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
1575
1722
 
@@ -1627,7 +1774,7 @@ If your icons are injected at build time, or you target browsers that support SV
1627
1774
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1628
1775
  <a title="Works in 'json/json' config block" href="#usage">
1629
1776
  <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1630
- <a title="Copy rule URL" target="_blank"
1777
+ <a title="Copy rule URL" target="_blank"
1631
1778
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-mv3-schema">
1632
1779
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1633
1780
  </h3>
@@ -1694,7 +1841,9 @@ If you intentionally target MV2 for a browser that still supports it (e.g. Firef
1694
1841
  <code>valid-service-worker</code>
1695
1842
  <a title="Included in recommended config" href="#usage">
1696
1843
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1697
- <a title="Copy rule URL" target="_blank"
1844
+ <a title="Accepts array w/ options" href="#usage">
1845
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1846
+ <a title="Copy rule URL" target="_blank"
1698
1847
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-service-worker">
1699
1848
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1700
1849
  </h3>
@@ -1703,6 +1852,12 @@ If you intentionally target MV2 for a browser that still supports it (e.g. Firef
1703
1852
 
1704
1853
  <summary>Enforces valid service worker lifecycle and isolation.</summary>
1705
1854
 
1855
+ <h4 id="valid-service-worker-options">Options</h4>
1856
+
1857
+ - `checkListenerTopLevel` (default `true`) – require `chrome.*.addListener()` calls at module top level <a title="Introduced in v2.5.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.5.0"><img height=14 alt="[Since v2.5.0]" src="https://img.shields.io/badge/since-v2.5.0-8a9199?style=flat-square" align="middle"></a>
1858
+ - `checkKeepaliveTimer` (default `true`) – flag sub-30s timers used as a keepalive workaround <a title="Introduced in v2.5.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.5.0"><img height=14 alt="[Since v2.5.0]" src="https://img.shields.io/badge/since-v2.5.0-8a9199?style=flat-square" align="middle"></a>
1859
+ - `checkDOMglobals` (default `true`) – flag DOM globals (`window`, `document`, `localStorage`) inside the service worker <a title="Introduced in v2.5.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.5.0"><img height=14 alt="[Since v2.5.0]" src="https://img.shields.io/badge/since-v2.5.0-8a9199?style=flat-square" align="middle"></a>
1860
+
1706
1861
  #### <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
1707
1862
 
1708
1863
  ```diff
@@ -1755,11 +1910,13 @@ If your background context isn't a service worker.
1755
1910
 
1756
1911
  <h3 id="valid-url-fields">
1757
1912
  <code>valid-url-fields</code>
1758
- <a title="Only works in 'json/json' config block" href="#usage">
1759
- <img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
1913
+ <a title="Included in recommended config" href="#usage">
1914
+ <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1915
+ <a title="Works in 'json/json' config block" href="#usage">
1916
+ <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1760
1917
  <a title="Accepts array w/ options" href="#usage">
1761
1918
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1762
- <a title="Copy rule URL" target="_blank"
1919
+ <a title="Copy rule URL" target="_blank"
1763
1920
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-url-fields">
1764
1921
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1765
1922
  </h3>
@@ -1770,10 +1927,10 @@ If your background context isn't a service worker.
1770
1927
 
1771
1928
  <h4 id="valid-url-fields-options">Options</h4>
1772
1929
 
1773
- - `checkURLfields` (default `true`) – validate URL fields (<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/chrome-settings-override">`chrome_settings_overrides`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/homepage-url">`homepage_url`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/oauth2">`oauth2.scopes`</a>, <a target="_blank" href="https://developer.chrome.com/docs/apps/autoupdate#update_url">`update_url`</a>)
1774
- - `checkMatchPatterns` (default `true`) – validate <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">match patterns</a> (in <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/content-scripts">`content_scripts`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable">`externally_connectable`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#host-permissions">`host_permissions`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions">`optional_host_permissions`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources">`web_accessible_resources`</a>)
1775
- - `allowedSchemes` (default `['https', 'file']`) – permitted URL schemes for <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">match patterns</a>
1776
- - `allowAllURLs` (default `false`) – allow unrestricted patterns (<a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">`<all_urls>`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">`https://*/*`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">`*://*/*`</a>)
1930
+ - `checkURLfields` (default `true`) – validate URL fields (<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/chrome-settings-override">`chrome_settings_overrides`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/homepage-url">`homepage_url`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/oauth2">`oauth2.scopes`</a>, <a target="_blank" href="https://developer.chrome.com/docs/apps/autoupdate#update_url">`update_url`</a>) <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1931
+ - `checkMatchPatterns` (default `true`) – validate <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">match patterns</a> (in <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/content-scripts">`content_scripts`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable">`externally_connectable`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#host-permissions">`host_permissions`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions">`optional_host_permissions`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources">`web_accessible_resources`</a>) <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1932
+ - `allowedSchemes` (default `['https', 'file']`) – permitted URL schemes for <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">match patterns</a> <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1933
+ - `allowAllURLs` (default `false`) – allow unrestricted patterns (<a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">`<all_urls>`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">`https://*/*`</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">`*://*/*`</a>) <a title="Introduced in v2.4.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0"><img height=14 alt="[Since v2.4.0]" src="https://img.shields.io/badge/since-v2.4.0-8a9199?style=flat-square" align="middle"></a>
1777
1934
 
1778
1935
  #### <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
1779
1936
 
@@ -1834,7 +1991,7 @@ If your URLs or patterns are generated at build time.
1834
1991
  <img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
1835
1992
  <a title="Accepts array w/ options" href="#usage">
1836
1993
  <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1837
- <a title="Copy rule URL" target="_blank"
1994
+ <a title="Copy rule URL" target="_blank"
1838
1995
  href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-version-field">
1839
1996
  <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1840
1997
  </h3>
@@ -1845,15 +2002,15 @@ If your URLs or patterns are generated at build time.
1845
2002
 
1846
2003
  <h4 id="valid-version-field-options">Options</h4>
1847
2004
 
1848
- - `versionType` (default `'chrome'`) – version format to enforce (`'chrome'`, `'semver'`, `'date'`)
1849
- - `allowFutureDate` (default `false`) – allow `version` dates later than the current date
1850
- - `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)
2005
+ - `versionType` (default `'chrome'`) – version format to enforce (`'chrome'`, `'semver'`, `'date'`) <a title="Introduced in v2.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.0.0"><img height=14 alt="[Since v2.0.0]" src="https://img.shields.io/badge/since-v2.0.0-8a9199?style=flat-square" align="middle"></a>
2006
+ - `allowFutureDate` (default `false`) – allow `version` dates later than the current date <a title="Introduced in v2.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.0.0"><img height=14 alt="[Since v2.0.0]" src="https://img.shields.io/badge/since-v2.0.0-8a9199?style=flat-square" align="middle"></a>
2007
+ - `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) <a title="Introduced in v2.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.0.0"><img height=14 alt="[Since v2.0.0]" src="https://img.shields.io/badge/since-v2.0.0-8a9199?style=flat-square" align="middle"></a>
1851
2008
 
1852
2009
  #### <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
1853
2010
 
1854
2011
  ```diff
1855
2012
  /* eslint chrome-extensions/valid-version-field: ['error', { versionType: 'date' }] */
1856
-
2013
+
1857
2014
  {
1858
2015
  "manifest_version": 3,
1859
2016
  ! "version": "2026.1.111",
@@ -1865,7 +2022,7 @@ If your URLs or patterns are generated at build time.
1865
2022
 
1866
2023
  ```diff
1867
2024
  /* eslint chrome-extensions/valid-version-field: ['error', { versionType: 'date' }] */
1868
-
2025
+
1869
2026
  {
1870
2027
  "manifest_version": 3,
1871
2028
  - "version": "2026.1.111",
@@ -1919,7 +2076,7 @@ If you don't care about version format consistency, or your version is injected
1919
2076
  ## <img height=30 width=27 align="top" src="https://api.iconify.design/ic/baseline-account-balance.svg?color=%232b2b2a"> License
1920
2077
 
1921
2078
  <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/src/branch/main/docs/LICENSE.md">
1922
- <img height=85 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/9e820e5d51/assets/images/logos/mit-license/red-pixelated.png"></a>
2079
+ <img height=80 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/9e820e5d51/assets/images/logos/mit-license/red-pixelated.png"></a>
1923
2080
  <br><br>
1924
2081
 
1925
2082
  <details>