eslint-plugin-greasemonkey 1.8.1 → 1.8.3
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 +21 -9
- package/package.json +4 -4
- package/src/index.js +4 -22
- package/src/rules/meta-order.js +2 -2
- package/src/rules/meta-spacing.js +1 -1
- package/src/rules/no-duplicate-keys.js +1 -1
- package/src/rules/no-invalid-grants.js +6 -4
- package/src/rules/no-invalid-headers.js +4 -3
- package/src/rules/no-missing-grants.js +3 -2
- package/src/rules/no-missing-resources.js +2 -2
- package/src/rules/prefer-match.js +1 -1
- package/src/rules/require-blank-line-after-meta-block.js +1 -1
- package/src/rules/require-homepage-pair.js +1 -1
- package/src/rules/require-matching-localized-fields.js +6 -5
- package/src/rules/require-required-fields.js +1 -1
- package/src/rules/require-space-before-meta-key.js +1 -1
- package/src/rules/require-update-download-pair.js +1 -1
- package/src/rules/require-user-js-filename.js +1 -1
- package/src/rules/valid-field-values.js +6 -6
- package/src/utils.js +6 -0
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
<img alt="[Latest Build]" src="https://img.shields.io/npm/v/eslint-plugin-greasemonkey?logo=icinga&style=for-the-badge&label=Latest%20Build&color=32fcee"></a>
|
|
7
7
|
<a href="#license">
|
|
8
8
|
<img alt="[License: MIT]" src="https://img.shields.io/badge/License-MIT-f1f20a.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
9
|
-
<
|
|
9
|
+
<a>
|
|
10
|
+
<img src="https://img.shields.io/npm/dm/eslint-plugin-greasemonkey?style=for-the-badge&logo=npm&color=black"></a>
|
|
10
11
|
<a target="_blank" href="https://eslint.org/">
|
|
11
12
|
<img alt="[Requires ESLint >=9.0.0]" src="https://img.shields.io/badge/Requires-ESLint_%3E%3D9.0.0-4B32C3?style=for-the-badge&logo=eslint"></a>
|
|
12
13
|
<br><br>
|
|
@@ -51,7 +52,7 @@ export default [
|
|
|
51
52
|
]
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
Available bundles: `recommended`, `strict
|
|
55
|
+
Available bundles: `recommended`, `strict` (everything), `problem` (deterministic bugs only), `tampermonkey`, `violentmonkey`, `greasemonkey`, `scriptcat`, `adguard`
|
|
55
56
|
|
|
56
57
|
**Note:** Rule config is either a severity string (`'off'`, `'warn'`, `'error'`) or an array `[severity, options]` when the rule accepts options.
|
|
57
58
|
|
|
@@ -1087,8 +1088,6 @@ If you prefer shorter URLs, or don't support users who strictly enforce subresou
|
|
|
1087
1088
|
|
|
1088
1089
|
#### See also
|
|
1089
1090
|
|
|
1090
|
-
- [`no-invalid-headers`](#no-invalid-headers)
|
|
1091
|
-
- [`require-required-fields`](#require-required-fields)
|
|
1092
1091
|
- <a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=sri">Tampermonkey — Subresource Integrity</a>
|
|
1093
1092
|
- <a target="_blank" href="https://docs.scriptcat.org/en/docs/dev/meta/#resource-integrity-verification">ScriptCat — Resource Integrity Verification</a>
|
|
1094
1093
|
|
|
@@ -1140,7 +1139,7 @@ If you prefer shorter URLs, or don't support users who strictly enforce subresou
|
|
|
1140
1139
|
|
|
1141
1140
|
#### When not to use it
|
|
1142
1141
|
|
|
1143
|
-
If you don't target Tampermonkey, ScriptCat or AdGuard (where `@updateURL` avoids re-downloading the full script on every update check).
|
|
1142
|
+
If you don't strictly target Tampermonkey, ScriptCat or AdGuard (where `@updateURL` avoids re-downloading the full script on every update check).
|
|
1144
1143
|
|
|
1145
1144
|
#### Introduced in
|
|
1146
1145
|
|
|
@@ -1148,7 +1147,6 @@ If you don't target Tampermonkey, ScriptCat or AdGuard (where `@updateURL` avoid
|
|
|
1148
1147
|
|
|
1149
1148
|
#### See also
|
|
1150
1149
|
|
|
1151
|
-
- [`require-homepage-pair`](#require-homepage-pair)
|
|
1152
1150
|
- <a target="_blank" href="https://www.tampermonkey.net/documentation.php?q=update_url#meta:updateURL">Tampermonkey — `@updateURL`</a>
|
|
1153
1151
|
- <a target="_blank" href="https://docs.scriptcat.org/en/docs/dev/meta/#updateurl">ScriptCat — `@updateURL`</a>
|
|
1154
1152
|
|
|
@@ -1262,7 +1260,7 @@ If you use a custom versioning scheme or URLs that aren't standard.
|
|
|
1262
1260
|
#### See also
|
|
1263
1261
|
|
|
1264
1262
|
- [`no-invalid-grants`](#no-invalid-grants)
|
|
1265
|
-
- [`no-
|
|
1263
|
+
- [`no-invalid-headers`](#no-invalid-headers)
|
|
1266
1264
|
|
|
1267
1265
|
<div align="center">
|
|
1268
1266
|
|
|
@@ -1274,7 +1272,7 @@ If you use a custom versioning scheme or URLs that aren't standard.
|
|
|
1274
1272
|
|
|
1275
1273
|
---
|
|
1276
1274
|
|
|
1277
|
-
## <img
|
|
1275
|
+
## <img width=30 align="top" src="https://api.iconify.design/boxicons/code-alt-filled.svg?color=%232b2b2a"> Shield embed
|
|
1278
1276
|
|
|
1279
1277
|
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/#readme">
|
|
1280
1278
|
<img height=32 alt="[Linted by eslint-plugin-greasemonkey]" src="https://img.shields.io/badge/Linted_by-eslint--plugin--greasemonkey-black?logo=eslint&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
@@ -1282,7 +1280,7 @@ If you use a custom versioning scheme or URLs that aren't standard.
|
|
|
1282
1280
|
#### HTML
|
|
1283
1281
|
|
|
1284
1282
|
```html
|
|
1285
|
-
<a href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/#readme">
|
|
1283
|
+
<a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-greasemonkey/#readme">
|
|
1286
1284
|
<img height=32 alt="[Linted by eslint-plugin-greasemonkey]" src="https://img.shields.io/badge/Linted_by-eslint--plugin--greasemonkey-black?logo=eslint&logoColor=white&labelColor=464646&style=for-the-badge"></a>
|
|
1287
1285
|
```
|
|
1288
1286
|
|
|
@@ -1316,6 +1314,20 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
1316
1314
|
|
|
1317
1315
|
## <img height=30 width=29 align="top" src="https://api.iconify.design/bxs/package.svg?color=%232b2b2a"> Related
|
|
1318
1316
|
|
|
1317
|
+
<!-- eslint-plugin-chrome-extensions -->
|
|
1318
|
+
|
|
1319
|
+
### <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/#readme"><img height=15 width=auto src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/e9128375d4/assets/images/icons/eslint/purple/icon16.png"> eslint-plugin-chrome-extensions</a>
|
|
1320
|
+
|
|
1321
|
+
<details>
|
|
1322
|
+
|
|
1323
|
+
<summary>ESLint rules for Chrome extensions.</summary><br>
|
|
1324
|
+
|
|
1325
|
+
> <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/#readme"><img width=555 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-chrome-extensions/0b5e3e49/assets/images/screenshots/vs-code/squiggles.png"></a>
|
|
1326
|
+
|
|
1327
|
+
> <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/#installation"><b>Install</b></a> / <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/#readme">Readme</a> / <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/#supported-rules">Supported rules</a>
|
|
1328
|
+
|
|
1329
|
+
</details>
|
|
1330
|
+
|
|
1319
1331
|
<!-- eslint-plugin-constructors -->
|
|
1320
1332
|
|
|
1321
1333
|
### <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-constructors/#readme"><img height=15 width=auto src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/e9128375d4/assets/images/icons/eslint/purple/icon16.png"> eslint-plugin-constructors</a>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-greasemonkey",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.3",
|
|
4
4
|
"description": "ESLint rules for Greasemonkey/Tampermonkey userscripts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -68,11 +68,11 @@
|
|
|
68
68
|
"@eslint/json": "^2.1.0",
|
|
69
69
|
"@eslint/markdown": "^8.0.3",
|
|
70
70
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
71
|
-
"eslint": "^10.
|
|
72
|
-
"eslint-plugin-constructors": "^1.4.
|
|
71
|
+
"eslint": "^10.12.0",
|
|
72
|
+
"eslint-plugin-constructors": "^1.4.1",
|
|
73
73
|
"eslint-plugin-eslint-plugin": "^7.6.2",
|
|
74
74
|
"eslint-plugin-import-x": "^4.17.1",
|
|
75
|
-
"eslint-plugin-n": "^18.4.
|
|
75
|
+
"eslint-plugin-n": "^18.4.1",
|
|
76
76
|
"eslint-plugin-no-secrets": "^2.3.3",
|
|
77
77
|
"eslint-plugin-no-unsanitized": "^4.1.5",
|
|
78
78
|
"eslint-plugin-promise": "^7.3.0",
|
package/src/index.js
CHANGED
|
@@ -22,7 +22,7 @@ import requireUpdateDownloadPair from './rules/require-update-download-pair.js'
|
|
|
22
22
|
import requireUserJsFilename from './rules/require-user-js-filename.js'
|
|
23
23
|
import validFieldValues from './rules/valid-field-values.js'
|
|
24
24
|
|
|
25
|
-
import { initDeprecatedAlias } from './utils.js'
|
|
25
|
+
import { bundleRules, initDeprecatedAlias } from './utils.js'
|
|
26
26
|
|
|
27
27
|
const plugin = {
|
|
28
28
|
rules: {
|
|
@@ -57,33 +57,15 @@ for (const entry of Object.entries(oldRules))
|
|
|
57
57
|
plugin.configs = {
|
|
58
58
|
recommended: {
|
|
59
59
|
plugins: { greasemonkey: plugin },
|
|
60
|
-
rules:
|
|
61
|
-
'greasemonkey/meta-spacing': 'error',
|
|
62
|
-
'greasemonkey/no-duplicate-keys': 'error',
|
|
63
|
-
'greasemonkey/no-invalid-grants': 'error',
|
|
64
|
-
'greasemonkey/no-invalid-headers': 'error',
|
|
65
|
-
'greasemonkey/no-missing-grants': 'error',
|
|
66
|
-
'greasemonkey/no-unused-grants': 'error',
|
|
67
|
-
'greasemonkey/no-missing-resources': 'error',
|
|
68
|
-
'greasemonkey/no-unused-resources': 'error',
|
|
69
|
-
'greasemonkey/prefer-match': 'error',
|
|
70
|
-
'greasemonkey/require-blank-line-after-meta-block': 'error',
|
|
71
|
-
'greasemonkey/require-matching-localized-fields': 'error',
|
|
72
|
-
'greasemonkey/require-required-fields': 'error',
|
|
73
|
-
'greasemonkey/require-space-before-meta-key': 'error',
|
|
74
|
-
'greasemonkey/require-user-js-filename': 'error',
|
|
75
|
-
'greasemonkey/valid-field-values': 'error'
|
|
76
|
-
}
|
|
60
|
+
rules: bundleRules(plugin.rules, rule => rule.meta.docs.recommended, 'greasemonkey')
|
|
77
61
|
},
|
|
78
62
|
strict: {
|
|
79
63
|
plugins: { greasemonkey: plugin },
|
|
80
|
-
rules:
|
|
64
|
+
rules: bundleRules(plugin.rules, () => true, 'greasemonkey')
|
|
81
65
|
},
|
|
82
66
|
problem: {
|
|
83
67
|
plugins: { greasemonkey: plugin },
|
|
84
|
-
rules:
|
|
85
|
-
.filter(([, rule]) => rule.meta.type == 'problem')
|
|
86
|
-
.map(([ruleId]) => [`greasemonkey/${ruleId}`, 'error']))
|
|
68
|
+
rules: bundleRules(plugin.rules, rule => rule.meta.type == 'problem', 'greasemonkey')
|
|
87
69
|
}
|
|
88
70
|
}
|
|
89
71
|
|
package/src/rules/meta-order.js
CHANGED
|
@@ -39,13 +39,13 @@ export default {
|
|
|
39
39
|
properties: {
|
|
40
40
|
order: {
|
|
41
41
|
type: 'array', items: { type: 'string' },
|
|
42
|
-
description: 'Metadata keys in preferred order
|
|
42
|
+
description: 'Metadata keys in preferred order'
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
additionalProperties: false
|
|
46
46
|
}],
|
|
47
47
|
defaultOptions: [{ order: [] }],
|
|
48
|
-
messages: { wrongOrder: '@{{first}} should appear before @{{second}}' }
|
|
48
|
+
messages: { wrongOrder: '@{{first}} should appear before @{{second}}.' }
|
|
49
49
|
},
|
|
50
50
|
|
|
51
51
|
create(context) {
|
|
@@ -22,7 +22,7 @@ export default {
|
|
|
22
22
|
additionalProperties: false
|
|
23
23
|
}],
|
|
24
24
|
defaultOptions: [{ spaces: 3 }],
|
|
25
|
-
messages: { misaligned: 'Metadata values should be aligned at column {{column}}' }
|
|
25
|
+
messages: { misaligned: 'Metadata values should be aligned at column {{column}}.' }
|
|
26
26
|
},
|
|
27
27
|
|
|
28
28
|
create(context) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { extractMetadata } from '../utils.js'
|
|
2
1
|
import { allAPIs, supportsAPI } from '../data/apis.js'
|
|
3
2
|
|
|
3
|
+
import { extractMetadata } from '../utils.js'
|
|
4
|
+
|
|
4
5
|
const managers = ['tampermonkey', 'violentmonkey', 'greasemonkey', 'scriptcat', 'adguard'],
|
|
5
6
|
specialGrants = new Set(['none', 'unsafeWindow', 'window.close', 'window.focus', 'window.onurlchange']),
|
|
6
7
|
allGrants = new Set([...allAPIs, ...specialGrants]),
|
|
@@ -37,7 +38,7 @@ export default {
|
|
|
37
38
|
defaultOptions: [{}],
|
|
38
39
|
messages: {
|
|
39
40
|
invalidGrant: 'Invalid @grant: "{{grant}}"',
|
|
40
|
-
unsupportedGrant: '"@{{grant}}" is not supported by {{target}} (only by {{supporting}})',
|
|
41
|
+
unsupportedGrant: '"@{{grant}}" is not supported by {{target}} (only by {{supporting}}).',
|
|
41
42
|
wrongCase: 'Invalid @grant: "{{grant}}" (did you mean "{{suggestion}}"?)'
|
|
42
43
|
}
|
|
43
44
|
},
|
|
@@ -46,14 +47,15 @@ export default {
|
|
|
46
47
|
const options = context.options[0] || {},
|
|
47
48
|
rawTarget = options.target ?? 'all',
|
|
48
49
|
targets = Array.isArray(rawTarget) ? rawTarget : [rawTarget],
|
|
49
|
-
|
|
50
|
+
rawAllowed = options.allowedGrants ?? [],
|
|
51
|
+
allowedGrants = new Set(Array.isArray(rawAllowed) ? rawAllowed : [rawAllowed])
|
|
50
52
|
return {
|
|
51
53
|
Program() {
|
|
52
54
|
const metaEntries = extractMetadata(context.sourceCode),
|
|
53
55
|
grantEntries = metaEntries.filter(entry => entry.key == 'grant')
|
|
54
56
|
for (const grant of grantEntries) {
|
|
55
57
|
const grantName = grant.value.trim()
|
|
56
|
-
if (specialGrants.has(grantName) || allowedGrants.
|
|
58
|
+
if (specialGrants.has(grantName) || allowedGrants.has(grantName)) continue
|
|
57
59
|
if (!allGrants.has(grantName)) {
|
|
58
60
|
const suggestion = sortedGrants.get(grantName.toLowerCase())
|
|
59
61
|
if (suggestion && suggestion != grantName)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { extractMetadata } from '../utils.js'
|
|
2
1
|
import { managerHeaders, managers, localizedHeaders, validHeaders } from '../data/headers.js'
|
|
3
2
|
|
|
3
|
+
import { extractMetadata } from '../utils.js'
|
|
4
|
+
|
|
4
5
|
function parseAllowedPattern(entry) {
|
|
5
6
|
if (typeof entry != 'string' || !entry.startsWith('/')) return null
|
|
6
7
|
const lastSlash = entry.lastIndexOf('/')
|
|
@@ -37,8 +38,8 @@ export default {
|
|
|
37
38
|
}],
|
|
38
39
|
defaultOptions: [{ allowedHeaders: [] }],
|
|
39
40
|
messages: {
|
|
40
|
-
invalidHeader: 'Invalid header: "@{{header}}"',
|
|
41
|
-
unsupportedHeader: '"@{{header}}" is not supported by {{target}} (only by {{supporting}})'
|
|
41
|
+
invalidHeader: 'Invalid header: "@{{header}}".',
|
|
42
|
+
unsupportedHeader: '"@{{header}}" is not supported by {{target}} (only by {{supporting}}).'
|
|
42
43
|
}
|
|
43
44
|
},
|
|
44
45
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { extractMetadata } from '../utils.js'
|
|
2
1
|
import { gmLegacyAPIs, gmModernAPIs, scAPIs } from '../data/apis.js'
|
|
3
2
|
|
|
3
|
+
import { extractMetadata } from '../utils.js'
|
|
4
|
+
|
|
4
5
|
const apis = new Set([...gmLegacyAPIs, ...gmModernAPIs, ...scAPIs]),
|
|
5
6
|
grantlessAPIs = new Set(['GM_info', 'GM.info']) // always available, no grant required
|
|
6
7
|
|
|
@@ -13,7 +14,7 @@ export default {
|
|
|
13
14
|
recommended: true
|
|
14
15
|
},
|
|
15
16
|
schema: [],
|
|
16
|
-
messages: { missingGrant: 'Missing @grant: "{{api}}"' }
|
|
17
|
+
messages: { missingGrant: 'Missing @grant: "{{api}}".' }
|
|
17
18
|
},
|
|
18
19
|
|
|
19
20
|
create(context) {
|
|
@@ -13,8 +13,8 @@ export default {
|
|
|
13
13
|
},
|
|
14
14
|
schema: [],
|
|
15
15
|
messages: {
|
|
16
|
-
missingResource: 'Missing @resource: "{{name}}"',
|
|
17
|
-
noMatchingResource: 'No declared @resource matches `{{pattern}}
|
|
16
|
+
missingResource: 'Missing @resource: "{{name}}".',
|
|
17
|
+
noMatchingResource: 'No declared @resource matches `{{pattern}}`.'
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
|
|
@@ -10,7 +10,7 @@ export default {
|
|
|
10
10
|
},
|
|
11
11
|
fixable: 'code',
|
|
12
12
|
schema: [],
|
|
13
|
-
messages: { missingPair: 'Missing @{{missing}} (required when @{{present}} is used)' }
|
|
13
|
+
messages: { missingPair: 'Missing @{{missing}} (required when @{{present}} is used).' }
|
|
14
14
|
},
|
|
15
15
|
|
|
16
16
|
create(context) {
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
meta: {
|
|
5
5
|
type: 'problem',
|
|
6
6
|
docs: {
|
|
7
|
-
description: 'Require matching localized name and description fields',
|
|
7
|
+
description: 'Require matching localized @name and @description fields',
|
|
8
8
|
category: 'Possible Errors',
|
|
9
9
|
recommended: true
|
|
10
10
|
},
|
|
@@ -22,12 +22,13 @@ export default {
|
|
|
22
22
|
additionalProperties: false
|
|
23
23
|
}],
|
|
24
24
|
defaultOptions: [{}],
|
|
25
|
-
messages: { missingPair: 'Missing matching @{{missing}} for @{{present}}' }
|
|
25
|
+
messages: { missingPair: 'Missing matching @{{missing}} for @{{present}}.' }
|
|
26
26
|
},
|
|
27
27
|
|
|
28
28
|
create(context) {
|
|
29
29
|
const options = context.options[0] || {},
|
|
30
|
-
|
|
30
|
+
rawLangs = options.ignoreLanguages ?? [],
|
|
31
|
+
ignoreLangs = new Set(Array.isArray(rawLangs) ? rawLangs : [rawLangs])
|
|
31
32
|
return {
|
|
32
33
|
Program() {
|
|
33
34
|
const metaEntries = extractMetadata(context.sourceCode),
|
|
@@ -36,14 +37,14 @@ export default {
|
|
|
36
37
|
nameLangs = new Set(nameEntries.map(entry => entry.key.split(':')[1])),
|
|
37
38
|
descLangs = new Set(descEntries.map(entry => entry.key.split(':')[1]))
|
|
38
39
|
for (const lang of nameLangs)
|
|
39
|
-
if (!
|
|
40
|
+
if (!ignoreLangs.has(lang) && !descLangs.has(lang))
|
|
40
41
|
context.report({
|
|
41
42
|
node: nameEntries.find(entry => entry.key == `name:${lang}`).comment,
|
|
42
43
|
messageId: 'missingPair',
|
|
43
44
|
data: { missing: `description:${lang}`, present: `name:${lang}` }
|
|
44
45
|
})
|
|
45
46
|
for (const lang of descLangs)
|
|
46
|
-
if (!
|
|
47
|
+
if (!ignoreLangs.has(lang) && !nameLangs.has(lang))
|
|
47
48
|
context.report({
|
|
48
49
|
node: descEntries.find(entry => entry.key == `description:${lang}`).comment,
|
|
49
50
|
messageId: 'missingPair',
|
|
@@ -24,7 +24,7 @@ export default {
|
|
|
24
24
|
additionalProperties: false
|
|
25
25
|
}],
|
|
26
26
|
defaultOptions: [{}],
|
|
27
|
-
messages: { missingField: 'Missing required metadata field: @{{field}}' }
|
|
27
|
+
messages: { missingField: 'Missing required metadata field: @{{field}}.' }
|
|
28
28
|
},
|
|
29
29
|
|
|
30
30
|
create(context) {
|
|
@@ -9,7 +9,7 @@ export default {
|
|
|
9
9
|
recommended: false
|
|
10
10
|
},
|
|
11
11
|
schema: [],
|
|
12
|
-
messages: { missingPair: 'Missing @{{missing}} (required when @{{present}} is used)' }
|
|
12
|
+
messages: { missingPair: 'Missing @{{missing}} (required when @{{present}} is used).' }
|
|
13
13
|
},
|
|
14
14
|
|
|
15
15
|
create(context) {
|
|
@@ -42,17 +42,17 @@ export default {
|
|
|
42
42
|
}],
|
|
43
43
|
defaultOptions: [{}],
|
|
44
44
|
messages: {
|
|
45
|
-
invalidVersion: 'Invalid @version: must be a valid {{versionType}} (expected format: {{example}})',
|
|
46
|
-
futureVersion: 'Invalid @version: date cannot be in the future',
|
|
47
|
-
invalidURL: 'Invalid URL for @{{field}}',
|
|
48
|
-
invalidGrant: 'Unknown @grant: "{{grant}}"'
|
|
45
|
+
invalidVersion: 'Invalid @version: must be a valid {{versionType}} (expected format: {{example}}).',
|
|
46
|
+
futureVersion: 'Invalid @version: date cannot be in the future.',
|
|
47
|
+
invalidURL: 'Invalid URL for @{{field}}.',
|
|
48
|
+
invalidGrant: 'Unknown @grant: "{{grant}}".'
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
|
|
52
52
|
create(context) {
|
|
53
53
|
const options = context.options[0] || {},
|
|
54
54
|
versionType = options.versionType || 'semver',
|
|
55
|
-
allowedGrants = options.allowedGrants || [],
|
|
55
|
+
allowedGrants = new Set(options.allowedGrants || []),
|
|
56
56
|
allowFutureDate = options.allowFutureDate ?? false,
|
|
57
57
|
timezone = options.timezone,
|
|
58
58
|
example = versionType == 'semver' ? '1.2.3' : 'YYYY.M.D or YYYY.MM.DD'
|
|
@@ -66,7 +66,7 @@ export default {
|
|
|
66
66
|
Program() {
|
|
67
67
|
const metaEntries = extractMetadata(context.sourceCode)
|
|
68
68
|
for (const entry of metaEntries) {
|
|
69
|
-
if (entry.key == 'grant' && allowedGrants.
|
|
69
|
+
if (entry.key == 'grant' && allowedGrants.size && !allowedGrants.has(entry.value))
|
|
70
70
|
context.report({ node: entry.comment, messageId: 'invalidGrant', data: { grant: entry.value }})
|
|
71
71
|
else if (entry.key == 'resource') {
|
|
72
72
|
const url = entry.value.trim().split(re.whitespace)[1]
|
package/src/utils.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
const re = { whitespace: /\s/ }
|
|
2
2
|
|
|
3
|
+
export function bundleRules(rules, predicate, pluginName) {
|
|
4
|
+
return Object.fromEntries(Object.entries(rules)
|
|
5
|
+
.filter(([, rule]) => predicate(rule))
|
|
6
|
+
.map(([ruleId]) => [`${pluginName}/${ruleId}`, 'error']))
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
export function extractMetadata(sourceCode) {
|
|
4
10
|
const comments = sourceCode.getAllComments(),
|
|
5
11
|
metaEntries = []
|