eslint-plugin-chrome-extensions 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +646 -33
- package/docs/LICENSE.md +1 -1
- package/package.json +46 -35
- package/src/data/apis.js +2 -3
- package/src/data/i18n.js +71 -0
- package/src/data/license.js +27 -0
- package/src/data/manifest.js +1 -0
- package/src/data/text-parser.js +11 -0
- package/src/index.js +53 -1
- package/src/rules/manifest-key-order.js +1 -2
- package/src/rules/manifest-spacing.js +2 -1
- package/src/rules/no-content-style-leak.js +5 -2
- package/src/rules/no-invalid-permissions.js +2 -2
- package/src/rules/no-missing-default-locale.js +91 -0
- package/src/rules/no-missing-i18n-keys.js +72 -0
- package/src/rules/no-missing-permissions.js +3 -3
- package/src/rules/no-missing-web-accessible-resources.js +4 -4
- package/src/rules/no-remote-code.js +5 -5
- package/src/rules/no-unrestricted-host-permissions.js +5 -4
- package/src/rules/no-unused-i18n-keys.js +54 -0
- package/src/rules/no-unused-permissions.js +3 -4
- package/src/rules/require-license-file.js +27 -0
- package/src/rules/require-short-name-when-useful.js +71 -0
- package/src/rules/valid-filenames.js +151 -0
- package/src/rules/valid-license-file.js +59 -0
- package/src/rules/valid-service-worker.js +2 -1
- package/src/rules/valid-url-fields.js +136 -0
- package/src/rules/valid-version-field.js +4 -2
- package/src/utils.js +12 -13
package/README.md
CHANGED
|
@@ -31,17 +31,16 @@ npm i -D eslint-plugin-chrome-extensions
|
|
|
31
31
|
Usage
|
|
32
32
|
</h2>
|
|
33
33
|
|
|
34
|
-
Add bundled configs to your `eslint.config.*js
|
|
34
|
+
Add bundled configs to your `eslint.config.*js` for each file type you need:
|
|
35
35
|
|
|
36
36
|
```js
|
|
37
37
|
...
|
|
38
38
|
import chromeExtensions from 'eslint-plugin-chrome-extensions'
|
|
39
|
-
import json from '@eslint/json'
|
|
40
39
|
|
|
41
40
|
export default [
|
|
42
41
|
// other configs
|
|
43
42
|
{
|
|
44
|
-
files: ['
|
|
43
|
+
files: ['**/*extension/**/*.{cjs,js,jsx,mjs,ts,tsx}'],
|
|
45
44
|
plugins: { 'chrome-extensions': chromeExtensions },
|
|
46
45
|
rules: {
|
|
47
46
|
...chromeExtensions.configs.recommended.rules,
|
|
@@ -49,17 +48,22 @@ export default [
|
|
|
49
48
|
}
|
|
50
49
|
},
|
|
51
50
|
{
|
|
52
|
-
files: ['**/manifest.json'],
|
|
53
|
-
plugins: { 'chrome-extensions': chromeExtensions, json },
|
|
51
|
+
files: ['**/manifest.json'], ...chromeExtensions.configs.manifest,
|
|
54
52
|
rules: {
|
|
55
53
|
...chromeExtensions.configs.manifest.rules,
|
|
56
|
-
'chrome-extensions/
|
|
54
|
+
'chrome-extensions/manifest-spacing': ['warn', { spaces: 4 }] // selectively tweak rule
|
|
57
55
|
}
|
|
58
|
-
}
|
|
56
|
+
},
|
|
57
|
+
{ files: ['**/*LICENSE*'], ...chromeExtensions.configs.license },
|
|
58
|
+
{ files: ['**/*extension/**/*.css'], ...chromeExtensions.configs.css },
|
|
59
|
+
{ files: ['**/*extension/**/*.html'], ...chromeExtensions.configs.html },
|
|
60
|
+
{ files: ['**/*extension/**/*.json'], ...chromeExtensions.configs.json },
|
|
61
|
+
{ files: ['**/*extension/**/*.json5'], ...chromeExtensions.configs.json5 },
|
|
62
|
+
{ files: ['**/*extension/**/*.jsonc'], ...chromeExtensions.configs.jsonc }
|
|
59
63
|
]
|
|
60
64
|
```
|
|
61
65
|
|
|
62
|
-
Available bundles: `recommended`, `strict` (everything), `problem` (deterministic bugs only), `security`, `manifest`
|
|
66
|
+
Available bundles: `recommended`, `strict` (everything), `problem` (deterministic bugs only), `security`, `manifest`, `license`, `css`, `html`, `json`, `json5`, `jsonc`
|
|
63
67
|
|
|
64
68
|
**Note:** Rule config is either a severity string (`'off'`, `'warn'`, `'error'`) or an array `[severity, options]` when the rule accepts options.
|
|
65
69
|
|
|
@@ -72,7 +76,7 @@ Available bundles: `recommended`, `strict` (everything), `problem` (deterministi
|
|
|
72
76
|
|
|
73
77
|
<h3 id="manifest-key-order">
|
|
74
78
|
<code>manifest-key-order</code>
|
|
75
|
-
<a title="Only works
|
|
79
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
76
80
|
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
77
81
|
<a title="Accepts eslint --fix" target="_blank" href="https://eslint.org/docs/latest/use/command-line-interface#--fix">
|
|
78
82
|
<img height=18 alt="[Auto-fixable]" src="https://img.shields.io/badge/Auto--fixable-3b5bdb?style=flat-square" align="middle"></a>
|
|
@@ -130,10 +134,10 @@ If you don't care about the order of manifest keys.
|
|
|
130
134
|
|
|
131
135
|
- [`require-mv3`](#require-mv3)
|
|
132
136
|
<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>
|
|
133
|
-
<a title="Works
|
|
137
|
+
<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>
|
|
134
138
|
- [`valid-mv3-schema`](#valid-mv3-schema)
|
|
135
139
|
<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>
|
|
136
|
-
<a title="Works
|
|
140
|
+
<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>
|
|
137
141
|
|
|
138
142
|
<div align="center">
|
|
139
143
|
|
|
@@ -147,7 +151,7 @@ If you don't care about the order of manifest keys.
|
|
|
147
151
|
|
|
148
152
|
<h3 id="manifest-spacing">
|
|
149
153
|
<code>manifest-spacing</code>
|
|
150
|
-
<a title="Only works
|
|
154
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
151
155
|
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
152
156
|
<a title="Accepts eslint --fix" target="_blank" href="https://eslint.org/docs/latest/use/command-line-interface#--fix">
|
|
153
157
|
<img height=18 alt="[Auto-fixable]" src="https://img.shields.io/badge/Auto--fixable-3b5bdb?style=flat-square" align="middle"></a>
|
|
@@ -215,12 +219,12 @@ If you don't care about visual consistency in your manifest.
|
|
|
215
219
|
#### See also
|
|
216
220
|
|
|
217
221
|
- [`manifest-key-order`](#manifest-key-order)
|
|
218
|
-
<a title="Only works
|
|
222
|
+
<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>
|
|
219
223
|
<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>
|
|
220
224
|
<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>
|
|
221
225
|
<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>
|
|
222
226
|
- [`no-duplicate-manifest-keys`](#no-duplicate-manifest-keys)
|
|
223
|
-
<a title="Only works
|
|
227
|
+
<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>
|
|
224
228
|
|
|
225
229
|
<div align="center">
|
|
226
230
|
|
|
@@ -351,7 +355,7 @@ If you don't want deprecation validation at all. For individual deprecated APIs
|
|
|
351
355
|
|
|
352
356
|
<h3 id="no-duplicate-manifest-keys">
|
|
353
357
|
<code>no-duplicate-manifest-keys</code>
|
|
354
|
-
<a title="Only works
|
|
358
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
355
359
|
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
356
360
|
<a title="Copy rule URL" target="_blank"
|
|
357
361
|
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-duplicate-manifest-keys">
|
|
@@ -399,12 +403,12 @@ If you rely on a Chromium fork resolving duplicate keys in a specific order.
|
|
|
399
403
|
#### See also
|
|
400
404
|
|
|
401
405
|
- [`manifest-key-order`](#manifest-key-order)
|
|
402
|
-
<a title="Only works
|
|
406
|
+
<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>
|
|
403
407
|
<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>
|
|
404
408
|
<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>
|
|
405
409
|
<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>
|
|
406
410
|
- [`no-unused-permissions`](#no-unused-permissions)
|
|
407
|
-
<a title="Only works
|
|
411
|
+
<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>
|
|
408
412
|
|
|
409
413
|
<div align="center">
|
|
410
414
|
|
|
@@ -558,7 +562,7 @@ If you trust every external caller and open tab, or you intentionally broadcast
|
|
|
558
562
|
<code>no-invalid-permissions</code>
|
|
559
563
|
<a title="Included in recommended config" href="#usage">
|
|
560
564
|
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
561
|
-
<a title="Works
|
|
565
|
+
<a title="Works in 'json/json' config block" href="#usage">
|
|
562
566
|
<img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
|
|
563
567
|
<a title="Accepts array w/ options" href="#usage">
|
|
564
568
|
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
@@ -613,7 +617,186 @@ If you don't want permission validation at all. For custom permissions from a Ch
|
|
|
613
617
|
- [`no-missing-permissions`](#no-missing-permissions)
|
|
614
618
|
<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>
|
|
615
619
|
- [`no-unused-permissions`](#no-unused-permissions)
|
|
616
|
-
<a title="Only works
|
|
620
|
+
<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>
|
|
621
|
+
|
|
622
|
+
<div align="center">
|
|
623
|
+
|
|
624
|
+
[Back to index ↑][epce-rules]
|
|
625
|
+
|
|
626
|
+
</div>
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
</details>
|
|
631
|
+
|
|
632
|
+
<h3 id="no-missing-default-locale">
|
|
633
|
+
<code>no-missing-default-locale</code>
|
|
634
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
635
|
+
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
636
|
+
<a title="Accepts array w/ options" href="#usage">
|
|
637
|
+
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
638
|
+
<a title="Copy rule URL" target="_blank"
|
|
639
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-missing-default-locale">
|
|
640
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
641
|
+
</h3>
|
|
642
|
+
|
|
643
|
+
<details>
|
|
644
|
+
|
|
645
|
+
<summary>Ensures <code>default_locale</code> is declared and every <code>_locales</code> key exists in it.</summary>
|
|
646
|
+
|
|
647
|
+
<h4 id="no-missing-default-locale-options">Options</h4>
|
|
648
|
+
|
|
649
|
+
- `ignoreKeys` (default `[]`) – keys to skip when checking the default locale
|
|
650
|
+
|
|
651
|
+
#### <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
|
|
652
|
+
|
|
653
|
+
```diff
|
|
654
|
+
// manifest.json
|
|
655
|
+
{
|
|
656
|
+
"manifest_version": 3,
|
|
657
|
+
"default_locale": "en",
|
|
658
|
+
"name": "__MSG_extName__"
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// _locales/en/messages.json
|
|
662
|
+
{
|
|
663
|
+
"extName": { "message": "My Extension" }
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// _locales/de/messages.json
|
|
667
|
+
{
|
|
668
|
+
"extName": { "message": "Meine Erweiterung" },
|
|
669
|
+
! "welcomeMsg": { "message": "Willkommen" }
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
#### <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
|
|
674
|
+
|
|
675
|
+
```diff
|
|
676
|
+
// manifest.json
|
|
677
|
+
{
|
|
678
|
+
"manifest_version": 3,
|
|
679
|
+
"default_locale": "en",
|
|
680
|
+
"name": "__MSG_extName__"
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// _locales/en/messages.json
|
|
684
|
+
{
|
|
685
|
+
"extName": { "message": "My Extension" },
|
|
686
|
+
+ "welcomeMsg": { "message": "Welcome" }
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// _locales/de/messages.json
|
|
690
|
+
{
|
|
691
|
+
"extName": { "message": "Meine Erweiterung" },
|
|
692
|
+
"welcomeMsg": { "message": "Willkommen" }
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
#### When not to use it
|
|
697
|
+
|
|
698
|
+
If your `_locales/` is externally populated at build time.
|
|
699
|
+
|
|
700
|
+
#### Introduced in
|
|
701
|
+
|
|
702
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0">v2.4.0</a> (October 13, 2026)
|
|
703
|
+
|
|
704
|
+
#### See also
|
|
705
|
+
|
|
706
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64"> <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/default-locale">Chrome for Developers — `default_locale`</a>
|
|
707
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64"> <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/api/i18n">Chrome for Developers — `i18n`</a>
|
|
708
|
+
|
|
709
|
+
<div align="center">
|
|
710
|
+
|
|
711
|
+
[Back to index ↑][epce-rules]
|
|
712
|
+
|
|
713
|
+
</div>
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
</details>
|
|
718
|
+
|
|
719
|
+
<h3 id="no-missing-i18n-keys">
|
|
720
|
+
<code>no-missing-i18n-keys</code>
|
|
721
|
+
<a title="Included in recommended config" href="#usage">
|
|
722
|
+
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
723
|
+
<a title="Works in 'json/json' config block" href="#usage">
|
|
724
|
+
<img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
|
|
725
|
+
<a title="Works in 'css/css' config block" href="#usage">
|
|
726
|
+
<img height=18 alt="[CSS]" src="https://img.shields.io/badge/CSS-dcd6f7?style=flat-square" align="middle"></a>
|
|
727
|
+
<a title="Works in 'html/html' config block" href="#usage">
|
|
728
|
+
<img height=18 alt="[HTML]" src="https://img.shields.io/badge/HTML-a8d8ea?style=flat-square" align="middle"></a>
|
|
729
|
+
<a title="Works in 'json/json' config block" href="#usage">
|
|
730
|
+
<img height=18 alt="[JSON]" src="https://img.shields.io/badge/JSON-a8e6cf?style=flat-square" align="middle"></a>
|
|
731
|
+
<a title="Works in 'json5' config block" href="#usage">
|
|
732
|
+
<img height=18 alt="[JSON5]" src="https://img.shields.io/badge/JSON5-c7e6b8?style=flat-square" align="middle"></a>
|
|
733
|
+
<a title="Works in 'jsonc' config block" href="#usage">
|
|
734
|
+
<img height=18 alt="[JSONC]" src="https://img.shields.io/badge/JSONC-e6e6a8?style=flat-square" align="middle"></a>
|
|
735
|
+
<a title="Accepts array w/ options" href="#usage">
|
|
736
|
+
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
737
|
+
<a title="Copy rule URL" target="_blank"
|
|
738
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-missing-i18n-keys">
|
|
739
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
740
|
+
</h3>
|
|
741
|
+
|
|
742
|
+
<details>
|
|
743
|
+
|
|
744
|
+
<summary>Flags i18n keys used but missing from <code>_locales/<default_locale>/messages.json</code>.</summary>
|
|
745
|
+
|
|
746
|
+
<h4 id="no-missing-i18n-keys-options">Options</h4>
|
|
747
|
+
|
|
748
|
+
- `ignoreKeys` (default `[]`) – keys to skip (e.g. `['customKey']`)
|
|
749
|
+
|
|
750
|
+
#### <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
|
|
751
|
+
|
|
752
|
+
```diff
|
|
753
|
+
// content.js
|
|
754
|
+
! chrome.i18n.getMessage('greeting')
|
|
755
|
+
|
|
756
|
+
// manifest.json
|
|
757
|
+
{
|
|
758
|
+
"manifest_version": 3,
|
|
759
|
+
! "name": "__MSG_extName__"
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// _locales/en/messages.json
|
|
763
|
+
{ "unrelated": { "message": "…" }}
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
#### <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
|
|
767
|
+
|
|
768
|
+
```diff
|
|
769
|
+
// content.js
|
|
770
|
+
chrome.i18n.getMessage('greeting')
|
|
771
|
+
|
|
772
|
+
// manifest.json
|
|
773
|
+
{
|
|
774
|
+
"manifest_version": 3,
|
|
775
|
+
"name": "__MSG_extName__"
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// _locales/en/messages.json
|
|
779
|
+
- { "unrelated": { "message": "…" }}
|
|
780
|
+
+ {
|
|
781
|
+
+ "greeting": { "message": "Hello" },
|
|
782
|
+
+ "extName": { "message": "My Extension" }
|
|
783
|
+
+ }
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
#### When not to use it
|
|
787
|
+
|
|
788
|
+
If your `_locales/` is externally populated at build time.
|
|
789
|
+
|
|
790
|
+
#### Introduced in
|
|
791
|
+
|
|
792
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0">v2.4.0</a> (October 13, 2026)
|
|
793
|
+
|
|
794
|
+
#### See also
|
|
795
|
+
|
|
796
|
+
- [`no-unused-i18n-keys`](#no-unused-i18n-keys)
|
|
797
|
+
<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>
|
|
798
|
+
<a title="Accepts array w/ options" href="#no-unused-i18n-keys-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
799
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64"> <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/api/i18n">Chrome for Developers — `i18n`</a>
|
|
617
800
|
|
|
618
801
|
<div align="center">
|
|
619
802
|
|
|
@@ -677,10 +860,10 @@ If you use APIs through aliases or wrappers that obscure the original call site.
|
|
|
677
860
|
|
|
678
861
|
- [`no-invalid-permissions`](#no-invalid-permissions)
|
|
679
862
|
<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>
|
|
680
|
-
<a title="Works
|
|
863
|
+
<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>
|
|
681
864
|
<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>
|
|
682
865
|
- [`no-unused-permissions`](#no-unused-permissions)
|
|
683
|
-
<a title="Only works
|
|
866
|
+
<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>
|
|
684
867
|
|
|
685
868
|
<div align="center">
|
|
686
869
|
|
|
@@ -811,10 +994,10 @@ If you intentionally target forks w/ relaxed CSPs. For individual patterns you s
|
|
|
811
994
|
|
|
812
995
|
- [`require-mv3`](#require-mv3)
|
|
813
996
|
<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>
|
|
814
|
-
<a title="Works
|
|
997
|
+
<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>
|
|
815
998
|
- [`valid-mv3-schema`](#valid-mv3-schema)
|
|
816
999
|
<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>
|
|
817
|
-
<a title="Works
|
|
1000
|
+
<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>
|
|
818
1001
|
|
|
819
1002
|
<div align="center">
|
|
820
1003
|
|
|
@@ -828,7 +1011,7 @@ If you intentionally target forks w/ relaxed CSPs. For individual patterns you s
|
|
|
828
1011
|
|
|
829
1012
|
<h3 id="no-unrestricted-host-permissions">
|
|
830
1013
|
<code>no-unrestricted-host-permissions</code>
|
|
831
|
-
<a title="Only works
|
|
1014
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
832
1015
|
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
833
1016
|
<a title="Accepts array w/ options" href="#usage">
|
|
834
1017
|
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
@@ -890,9 +1073,86 @@ If you legitimately need broad access (e.g. ad blockers or dev tools).
|
|
|
890
1073
|
|
|
891
1074
|
</details>
|
|
892
1075
|
|
|
1076
|
+
<h3 id="no-unused-i18n-keys">
|
|
1077
|
+
<code>no-unused-i18n-keys</code>
|
|
1078
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
1079
|
+
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
1080
|
+
<a title="Accepts array w/ options" href="#usage">
|
|
1081
|
+
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
1082
|
+
<a title="Copy rule URL" target="_blank"
|
|
1083
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-unused-i18n-keys">
|
|
1084
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
1085
|
+
</h3>
|
|
1086
|
+
|
|
1087
|
+
<details>
|
|
1088
|
+
|
|
1089
|
+
<summary>Flags i18n keys in <code>_locales/<default_locale>/messages.json</code> that are never referenced.</summary>
|
|
1090
|
+
|
|
1091
|
+
<h4 id="no-unused-i18n-keys-options">Options</h4>
|
|
1092
|
+
|
|
1093
|
+
- `ignoreKeys` (default `[]`) – keys to always treat as used (e.g. `['customKey']`)
|
|
1094
|
+
- `scanExtensions` (default `['cjs', 'css', 'htm', 'html', 'js', 'json', 'jsx', 'md', 'mjs', 'svg', 'ts', 'tsx', 'txt']`) – file extensions to scan for references
|
|
1095
|
+
|
|
1096
|
+
#### <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
|
|
1097
|
+
|
|
1098
|
+
```diff
|
|
1099
|
+
// _locales/en/messages.json
|
|
1100
|
+
{
|
|
1101
|
+
"usedKey": { "message": "Used message" },
|
|
1102
|
+
! "unusedKey": { "message": "Unused message" }
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// content.js
|
|
1106
|
+
chrome.i18n.getMessage('usedKey')
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
#### <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
|
|
1110
|
+
|
|
1111
|
+
```diff
|
|
1112
|
+
// _locales/en/messages.json
|
|
1113
|
+
{
|
|
1114
|
+
"usedKey": { "message": "Used message" }
|
|
1115
|
+
- "unusedKey": { "message": "Unused message" }
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
// content.js
|
|
1119
|
+
chrome.i18n.getMessage('usedKey')
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
#### When not to use it
|
|
1123
|
+
|
|
1124
|
+
If your i18n keys are referenced dynamically.
|
|
1125
|
+
|
|
1126
|
+
#### Introduced in
|
|
1127
|
+
|
|
1128
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0">v2.4.0</a> (October 13, 2026)
|
|
1129
|
+
|
|
1130
|
+
#### See also
|
|
1131
|
+
|
|
1132
|
+
- [`no-missing-i18n-keys`](#no-missing-i18n-keys)
|
|
1133
|
+
<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>
|
|
1134
|
+
<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>
|
|
1135
|
+
<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>
|
|
1136
|
+
<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>
|
|
1137
|
+
<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>
|
|
1138
|
+
<a title="Works in 'json5' config block" href="#usage"><img height=14 alt="[JSON5]" src="https://img.shields.io/badge/JSON5-c7e6b8?style=flat-square" align="middle"></a>
|
|
1139
|
+
<a title="Works in 'jsonc' config block" href="#usage"><img height=14 alt="[JSONC]" src="https://img.shields.io/badge/JSONC-e6e6a8?style=flat-square" align="middle"></a>
|
|
1140
|
+
<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>
|
|
1141
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64"> <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/api/i18n">Chrome for Developers — `i18n`</a>
|
|
1142
|
+
|
|
1143
|
+
<div align="center">
|
|
1144
|
+
|
|
1145
|
+
[Back to index ↑][epce-rules]
|
|
1146
|
+
|
|
1147
|
+
</div>
|
|
1148
|
+
|
|
1149
|
+
---
|
|
1150
|
+
|
|
1151
|
+
</details>
|
|
1152
|
+
|
|
893
1153
|
<h3 id="no-unused-permissions">
|
|
894
1154
|
<code>no-unused-permissions</code>
|
|
895
|
-
<a title="Only works
|
|
1155
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
896
1156
|
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
897
1157
|
<a title="Copy rule URL" target="_blank"
|
|
898
1158
|
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-unused-permissions">
|
|
@@ -940,7 +1200,7 @@ If you access the granted API through an alias or computed property rather than
|
|
|
940
1200
|
|
|
941
1201
|
- [`no-invalid-permissions`](#no-invalid-permissions)
|
|
942
1202
|
<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>
|
|
943
|
-
<a title="Works
|
|
1203
|
+
<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>
|
|
944
1204
|
<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>
|
|
945
1205
|
- [`no-missing-permissions`](#no-missing-permissions)
|
|
946
1206
|
<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>
|
|
@@ -955,11 +1215,64 @@ If you access the granted API through an alias or computed property rather than
|
|
|
955
1215
|
|
|
956
1216
|
</details>
|
|
957
1217
|
|
|
1218
|
+
<h3 id="require-license-file">
|
|
1219
|
+
<code>require-license-file</code>
|
|
1220
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
1221
|
+
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
1222
|
+
<a title="Copy rule URL" target="_blank"
|
|
1223
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23require-license-file">
|
|
1224
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
1225
|
+
</h3>
|
|
1226
|
+
|
|
1227
|
+
<details>
|
|
1228
|
+
|
|
1229
|
+
<summary>Requires a license file in the extension.</summary>
|
|
1230
|
+
|
|
1231
|
+
#### <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
|
|
1232
|
+
|
|
1233
|
+
```diff
|
|
1234
|
+
// files
|
|
1235
|
+
/extension/manifest.json
|
|
1236
|
+
!
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
#### <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
|
|
1240
|
+
|
|
1241
|
+
```diff
|
|
1242
|
+
// files
|
|
1243
|
+
/extension/manifest.json
|
|
1244
|
+
+ /extension/LICENSE
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
#### When not to use it
|
|
1248
|
+
|
|
1249
|
+
If you intentionally omit a license, or it's injected at build time.
|
|
1250
|
+
|
|
1251
|
+
#### Introduced in
|
|
1252
|
+
|
|
1253
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0">v2.4.0</a> (October 13, 2026)
|
|
1254
|
+
|
|
1255
|
+
#### See also
|
|
1256
|
+
|
|
1257
|
+
- [`valid-license-file`](#valid-license-file)
|
|
1258
|
+
<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>
|
|
1259
|
+
<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>
|
|
1260
|
+
|
|
1261
|
+
<div align="center">
|
|
1262
|
+
|
|
1263
|
+
[Back to index ↑][epce-rules]
|
|
1264
|
+
|
|
1265
|
+
</div>
|
|
1266
|
+
|
|
1267
|
+
---
|
|
1268
|
+
|
|
1269
|
+
</details>
|
|
1270
|
+
|
|
958
1271
|
<h3 id="require-mv3">
|
|
959
1272
|
<code>require-mv3</code>
|
|
960
1273
|
<a title="Included in recommended config" href="#usage">
|
|
961
1274
|
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
962
|
-
<a title="Works
|
|
1275
|
+
<a title="Works in 'json/json' config block" href="#usage">
|
|
963
1276
|
<img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
|
|
964
1277
|
<a title="Copy rule URL" target="_blank"
|
|
965
1278
|
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23require-mv3">
|
|
@@ -1003,7 +1316,234 @@ If you intentionally target MV2 for a browser that still supports it (e.g. Firef
|
|
|
1003
1316
|
|
|
1004
1317
|
- [`valid-mv3-schema`](#valid-mv3-schema)
|
|
1005
1318
|
<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>
|
|
1006
|
-
<a title="Works
|
|
1319
|
+
<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>
|
|
1320
|
+
|
|
1321
|
+
<div align="center">
|
|
1322
|
+
|
|
1323
|
+
[Back to index ↑][epce-rules]
|
|
1324
|
+
|
|
1325
|
+
</div>
|
|
1326
|
+
|
|
1327
|
+
---
|
|
1328
|
+
|
|
1329
|
+
</details>
|
|
1330
|
+
|
|
1331
|
+
<h3 id="require-short-name-when-useful">
|
|
1332
|
+
<code>require-short-name-when-useful</code>
|
|
1333
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
1334
|
+
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
1335
|
+
<a title="Accepts array w/ options" href="#usage">
|
|
1336
|
+
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
1337
|
+
<a title="Copy rule URL" target="_blank"
|
|
1338
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23require-short-name-when-useful">
|
|
1339
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
1340
|
+
</h3>
|
|
1341
|
+
|
|
1342
|
+
<details>
|
|
1343
|
+
|
|
1344
|
+
<summary>Requires <code>short_name</code> when <code>name</code> exceeds 12 chars.</summary>
|
|
1345
|
+
|
|
1346
|
+
<h4 id="require-short-name-when-useful-options">Options</h4>
|
|
1347
|
+
|
|
1348
|
+
- `maxNameLength` (default `12`) – length of `name` above which `short_name` is required
|
|
1349
|
+
- `always` (default `false`) – require `short_name` regardless of `name` length
|
|
1350
|
+
- `checkRedundant` (default `false`) – also flag `short_name` that duplicates `name`
|
|
1351
|
+
|
|
1352
|
+
#### <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
|
|
1353
|
+
|
|
1354
|
+
```diff
|
|
1355
|
+
{
|
|
1356
|
+
"manifest_version": 3,
|
|
1357
|
+
! "name": "Extension Infinity"
|
|
1358
|
+
}
|
|
1359
|
+
```
|
|
1360
|
+
|
|
1361
|
+
#### <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
|
|
1362
|
+
|
|
1363
|
+
```diff
|
|
1364
|
+
{
|
|
1365
|
+
"manifest_version": 3,
|
|
1366
|
+
"name": "Extension Infinity",
|
|
1367
|
+
+ "short_name": "Extension ∞"
|
|
1368
|
+
}
|
|
1369
|
+
```
|
|
1370
|
+
|
|
1371
|
+
#### When not to use it
|
|
1372
|
+
|
|
1373
|
+
If you primarily target a browser that doesn't support `short_name`.
|
|
1374
|
+
|
|
1375
|
+
#### Introduced in
|
|
1376
|
+
|
|
1377
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0">v2.4.0</a> (October 13, 2026)
|
|
1378
|
+
|
|
1379
|
+
#### See also
|
|
1380
|
+
|
|
1381
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64"> <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/short-name">Chrome for Developers — `short_name`</a>
|
|
1382
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64"> <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/name">Chrome for Developers — `name`</a>
|
|
1383
|
+
|
|
1384
|
+
<div align="center">
|
|
1385
|
+
|
|
1386
|
+
[Back to index ↑][epce-rules]
|
|
1387
|
+
|
|
1388
|
+
</div>
|
|
1389
|
+
|
|
1390
|
+
---
|
|
1391
|
+
|
|
1392
|
+
</details>
|
|
1393
|
+
|
|
1394
|
+
<h3 id="valid-filenames">
|
|
1395
|
+
<code>valid-filenames</code>
|
|
1396
|
+
<a title="Included in recommended config" href="#usage">
|
|
1397
|
+
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
1398
|
+
<a title="Works in 'json/json' config block" href="#usage">
|
|
1399
|
+
<img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
|
|
1400
|
+
<a title="Works in 'css/css' config block" href="#usage">
|
|
1401
|
+
<img height=18 alt="[CSS]" src="https://img.shields.io/badge/CSS-dcd6f7?style=flat-square" align="middle"></a>
|
|
1402
|
+
<a title="Works in 'html/html' config block" href="#usage">
|
|
1403
|
+
<img height=18 alt="[HTML]" src="https://img.shields.io/badge/HTML-a8d8ea?style=flat-square" align="middle"></a>
|
|
1404
|
+
<a title="Works in 'json/json' config block" href="#usage">
|
|
1405
|
+
<img height=18 alt="[JSON]" src="https://img.shields.io/badge/JSON-a8e6cf?style=flat-square" align="middle"></a>
|
|
1406
|
+
<a title="Works in 'json5' config block" href="#usage">
|
|
1407
|
+
<img height=18 alt="[JSON5]" src="https://img.shields.io/badge/JSON5-c7e6b8?style=flat-square" align="middle"></a>
|
|
1408
|
+
<a title="Works in 'jsonc' config block" href="#usage">
|
|
1409
|
+
<img height=18 alt="[JSONC]" src="https://img.shields.io/badge/JSONC-e6e6a8?style=flat-square" align="middle"></a>
|
|
1410
|
+
<a title="Accepts array w/ options" href="#usage">
|
|
1411
|
+
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
1412
|
+
<a title="Copy rule URL" target="_blank"
|
|
1413
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-filenames">
|
|
1414
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
1415
|
+
</h3>
|
|
1416
|
+
|
|
1417
|
+
<details>
|
|
1418
|
+
|
|
1419
|
+
<summary>Enforces valid filenames and paths.</summary>
|
|
1420
|
+
|
|
1421
|
+
<h4 id="valid-filenames-options">Options</h4>
|
|
1422
|
+
|
|
1423
|
+
- `noReservedPrefix` (default `true`) – disallow filenames/dirs starting w/ `_` (except `_locales`)
|
|
1424
|
+
- `noSpecialChars` (default `true`) – warn on chars outside `a-z`, `0-9`, `-`, `_`, `.`
|
|
1425
|
+
- `checkFileExists` (default `true`) – verify files referenced in `manifest.json` actually exist
|
|
1426
|
+
- `enforceCaseSensitivity` (default `true`) – verify manifest references match actual file case
|
|
1427
|
+
- `maxFullPathLength` (default `260`) – max full path char length
|
|
1428
|
+
|
|
1429
|
+
#### <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
|
|
1430
|
+
|
|
1431
|
+
```diff
|
|
1432
|
+
// files
|
|
1433
|
+
! /extension/_metadata/app.json
|
|
1434
|
+
! /extension/content script.js
|
|
1435
|
+
|
|
1436
|
+
// manifest.json
|
|
1437
|
+
{
|
|
1438
|
+
! "icons": { "16": "Icon16.png" },
|
|
1439
|
+
! "background": { "service_worker": "missing-worker.js" }
|
|
1440
|
+
}
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1443
|
+
#### <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
|
|
1444
|
+
|
|
1445
|
+
```diff
|
|
1446
|
+
- /extension/_metadata/app.json
|
|
1447
|
+
+ /extension/metadata/app.json
|
|
1448
|
+
- /extension/content script.js
|
|
1449
|
+
+ /extension/content-script.js
|
|
1450
|
+
|
|
1451
|
+
// manifest.json
|
|
1452
|
+
{
|
|
1453
|
+
- "icons": { "16": "Icon16.png" },
|
|
1454
|
+
+ "icons": { "16": "icon16.png" },
|
|
1455
|
+
- "background": { "service_worker": "missing-worker.js" }
|
|
1456
|
+
+ "background": { "service_worker": "service-worker.js" }
|
|
1457
|
+
}
|
|
1458
|
+
```
|
|
1459
|
+
|
|
1460
|
+
#### When not to use it
|
|
1461
|
+
|
|
1462
|
+
If you don't use conventional filenames or paths, or they're generated at build time.
|
|
1463
|
+
|
|
1464
|
+
#### Introduced in
|
|
1465
|
+
|
|
1466
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0">v2.4.0</a> (October 13, 2026)
|
|
1467
|
+
|
|
1468
|
+
#### See also
|
|
1469
|
+
|
|
1470
|
+
- [`no-missing-web-accessible-resources`](#no-missing-web-accessible-resources)
|
|
1471
|
+
<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>
|
|
1472
|
+
- [`valid-manifest-icons`](#valid-manifest-icons)
|
|
1473
|
+
<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>
|
|
1474
|
+
<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>
|
|
1475
|
+
|
|
1476
|
+
<div align="center">
|
|
1477
|
+
|
|
1478
|
+
[Back to index ↑][epce-rules]
|
|
1479
|
+
|
|
1480
|
+
</div>
|
|
1481
|
+
|
|
1482
|
+
---
|
|
1483
|
+
|
|
1484
|
+
</details>
|
|
1485
|
+
|
|
1486
|
+
<h3 id="valid-license-file">
|
|
1487
|
+
<code>valid-license-file</code>
|
|
1488
|
+
<a title="Only works in 'license' config block" href="#usage">
|
|
1489
|
+
<img height=18 alt="[License only]" src="https://img.shields.io/badge/License_only-559bff?style=flat-square" align="middle"></a>
|
|
1490
|
+
<a title="Accepts array w/ options" href="#usage">
|
|
1491
|
+
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
1492
|
+
<a title="Copy rule URL" target="_blank"
|
|
1493
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-license-file">
|
|
1494
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
1495
|
+
</h3>
|
|
1496
|
+
|
|
1497
|
+
<details>
|
|
1498
|
+
|
|
1499
|
+
<summary>Validates SPDX identifiers in license files.</summary>
|
|
1500
|
+
|
|
1501
|
+
<h4 id="valid-license-file-options">Options</h4>
|
|
1502
|
+
|
|
1503
|
+
- `requireSPDX` (default `false`) – require <a target="_blank" href="https://spdx.dev/learn/handling-license-info/">`SPDX-License-Identifier`</a> in the license
|
|
1504
|
+
- `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
|
|
1505
|
+
|
|
1506
|
+
#### <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
|
|
1507
|
+
|
|
1508
|
+
```diff
|
|
1509
|
+
/* eslint chrome-extensions/valid-license-file: ['error', { requireSPDX: true, allowedLicenses: ['MIT'] }] */
|
|
1510
|
+
|
|
1511
|
+
// LICENSE.md
|
|
1512
|
+
|
|
1513
|
+
MIT License
|
|
1514
|
+
|
|
1515
|
+
Copyright © 2026 You
|
|
1516
|
+
|
|
1517
|
+
!
|
|
1518
|
+
```
|
|
1519
|
+
|
|
1520
|
+
#### <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
|
|
1521
|
+
|
|
1522
|
+
```diff
|
|
1523
|
+
/* eslint chrome-extensions/valid-license-file: ['error', { requireSPDX: true, allowedLicenses: ['MIT'] }] */
|
|
1524
|
+
|
|
1525
|
+
// LICENSE.md
|
|
1526
|
+
|
|
1527
|
+
MIT License
|
|
1528
|
+
|
|
1529
|
+
Copyright © 2026 You
|
|
1530
|
+
|
|
1531
|
+
+ SPDX-License-Identifier: MIT
|
|
1532
|
+
```
|
|
1533
|
+
|
|
1534
|
+
#### When not to use it
|
|
1535
|
+
|
|
1536
|
+
If your license is injected at build time, or you use a license w/ no SPDX identifier.
|
|
1537
|
+
|
|
1538
|
+
#### Introduced in
|
|
1539
|
+
|
|
1540
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0">v2.4.0</a> (October 13, 2026)
|
|
1541
|
+
|
|
1542
|
+
#### See also
|
|
1543
|
+
|
|
1544
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=spdx.org&sz=64"> <a target="_blank" href="https://spdx.org/licenses/">SPDX — License List</a>
|
|
1545
|
+
- [`require-license-file`](#require-license-file)
|
|
1546
|
+
<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>
|
|
1007
1547
|
|
|
1008
1548
|
<div align="center">
|
|
1009
1549
|
|
|
@@ -1017,7 +1557,7 @@ If you intentionally target MV2 for a browser that still supports it (e.g. Firef
|
|
|
1017
1557
|
|
|
1018
1558
|
<h3 id="valid-manifest-icons">
|
|
1019
1559
|
<code>valid-manifest-icons</code>
|
|
1020
|
-
<a title="Only works
|
|
1560
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
1021
1561
|
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
1022
1562
|
<a title="Accepts array w/ options" href="#usage">
|
|
1023
1563
|
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
@@ -1090,7 +1630,7 @@ If your icons are injected at build time, or you target browsers that support SV
|
|
|
1090
1630
|
<code>valid-mv3-schema</code>
|
|
1091
1631
|
<a title="Included in recommended config" href="#usage">
|
|
1092
1632
|
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
1093
|
-
<a title="Works
|
|
1633
|
+
<a title="Works in 'json/json' config block" href="#usage">
|
|
1094
1634
|
<img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
|
|
1095
1635
|
<a title="Copy rule URL" target="_blank"
|
|
1096
1636
|
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-mv3-schema">
|
|
@@ -1140,7 +1680,7 @@ If you intentionally target MV2 for a browser that still supports it (e.g. Firef
|
|
|
1140
1680
|
|
|
1141
1681
|
- [`require-mv3`](#require-mv3)
|
|
1142
1682
|
<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>
|
|
1143
|
-
<a title="Works
|
|
1683
|
+
<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>
|
|
1144
1684
|
- [`no-deprecated-apis`](#no-deprecated-apis)
|
|
1145
1685
|
<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>
|
|
1146
1686
|
<a title="Accepts array w/ options" href="#no-deprecated-apis-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
@@ -1202,7 +1742,7 @@ If your background context isn't a service worker.
|
|
|
1202
1742
|
|
|
1203
1743
|
- [`require-mv3`](#require-mv3)
|
|
1204
1744
|
<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>
|
|
1205
|
-
<a title="Works
|
|
1745
|
+
<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>
|
|
1206
1746
|
- [`no-remote-code`](#no-remote-code)
|
|
1207
1747
|
<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>
|
|
1208
1748
|
<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>
|
|
@@ -1218,11 +1758,84 @@ If your background context isn't a service worker.
|
|
|
1218
1758
|
|
|
1219
1759
|
</details>
|
|
1220
1760
|
|
|
1761
|
+
<h3 id="valid-url-fields">
|
|
1762
|
+
<code>valid-url-fields</code>
|
|
1763
|
+
<a title="Only works in 'json/json' config block" href="#usage">
|
|
1764
|
+
<img height=18 alt="[Manifest only]" src="https://img.shields.io/badge/Manifest_only-999999?style=flat-square" align="middle"></a>
|
|
1765
|
+
<a title="Accepts array w/ options" href="#usage">
|
|
1766
|
+
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|
|
1767
|
+
<a title="Copy rule URL" target="_blank"
|
|
1768
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23valid-url-fields">
|
|
1769
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
1770
|
+
</h3>
|
|
1771
|
+
|
|
1772
|
+
<details>
|
|
1773
|
+
|
|
1774
|
+
<summary>Validates URLs and match patterns in manifest fields.</summary>
|
|
1775
|
+
|
|
1776
|
+
<h4 id="valid-url-fields-options">Options</h4>
|
|
1777
|
+
|
|
1778
|
+
- `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>)
|
|
1779
|
+
- `checkMatchPatterns` (default `true`) – validate match patterns (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>)
|
|
1780
|
+
- `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>
|
|
1781
|
+
- `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>)
|
|
1782
|
+
|
|
1783
|
+
#### <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
|
|
1784
|
+
|
|
1785
|
+
```diff
|
|
1786
|
+
{
|
|
1787
|
+
"manifest_version": 3,
|
|
1788
|
+
! "homepage_url": "not-a-url",
|
|
1789
|
+
! "host_permissions": ["https://*"],
|
|
1790
|
+
! "content_scripts": [{ "js": ["content.js"], "matches": ["*://*foo.com/*"] }],
|
|
1791
|
+
! "web_accessible_resources": [{ "resources": ["logo.png"], "matches": ["https://example.com/specific-path"] }]
|
|
1792
|
+
}
|
|
1793
|
+
```
|
|
1794
|
+
|
|
1795
|
+
#### <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
|
|
1796
|
+
|
|
1797
|
+
```diff
|
|
1798
|
+
{
|
|
1799
|
+
"manifest_version": 3,
|
|
1800
|
+
- "homepage_url": "not-a-url",
|
|
1801
|
+
+ "homepage_url": "https://example.com",
|
|
1802
|
+
- "host_permissions": ["https://*"],
|
|
1803
|
+
+ "host_permissions": ["https://example.com/*"],
|
|
1804
|
+
- "content_scripts": [{ "js": ["content.js"], "matches": ["*://*foo.com/*"] }],
|
|
1805
|
+
+ "content_scripts": [{ "js": ["content.js"], "matches": ["*://*.foo.com/*"] }],
|
|
1806
|
+
- "web_accessible_resources": [{ "resources": ["logo.png"], "matches": ["https://example.com/specific-path"] }]
|
|
1807
|
+
+ "web_accessible_resources": [{ "resources": ["logo.png"], "matches": ["https://example.com/*"] }]
|
|
1808
|
+
}
|
|
1809
|
+
```
|
|
1810
|
+
|
|
1811
|
+
#### When not to use it
|
|
1812
|
+
|
|
1813
|
+
If your URLs or match patterns are generated at build time.
|
|
1814
|
+
|
|
1815
|
+
#### Introduced in
|
|
1816
|
+
|
|
1817
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.4.0">v2.4.0</a> (October 13, 2026)
|
|
1818
|
+
|
|
1819
|
+
#### See also
|
|
1820
|
+
|
|
1821
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64"> <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions">Chrome for Developers — Declare permissions</a>
|
|
1822
|
+
- <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64"> <a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns">Chrome for Developers — Match patterns</a>
|
|
1823
|
+
|
|
1824
|
+
<div align="center">
|
|
1825
|
+
|
|
1826
|
+
[Back to index ↑][epce-rules]
|
|
1827
|
+
|
|
1828
|
+
</div>
|
|
1829
|
+
|
|
1830
|
+
---
|
|
1831
|
+
|
|
1832
|
+
</details>
|
|
1833
|
+
|
|
1221
1834
|
<h3 id="valid-version-field">
|
|
1222
1835
|
<code>valid-version-field</code>
|
|
1223
1836
|
<a title="Included in recommended config" href="#usage">
|
|
1224
1837
|
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
1225
|
-
<a title="Works
|
|
1838
|
+
<a title="Works in 'json/json' config block" href="#usage">
|
|
1226
1839
|
<img height=18 alt="[Manifest]" src="https://img.shields.io/badge/Manifest-999999?style=flat-square" align="middle"></a>
|
|
1227
1840
|
<a title="Accepts array w/ options" href="#usage">
|
|
1228
1841
|
<img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
|