@gitlab/eslint-plugin 23.0.0 → 24.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/docs/rules.md +0 -2
- package/lib/plugin.js +0 -2
- package/lib/rules/vue-require-required-key.js +1 -1
- package/lib/vue-fragments.js +1 -2
- package/package.json +9 -9
- package/docs/rules/vue-prefer-dollar-scopedslots.md +0 -62
- package/docs/rules/vue-slot-name-casing.md +0 -39
- package/lib/rules/vue-prefer-dollar-scopedslots.js +0 -64
- package/lib/rules/vue-slot-name-casing.js +0 -64
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @gitlab/eslint-plugin
|
|
2
2
|
|
|
3
|
+
## 24.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 830e78c: ESLint 10 compatibility
|
|
8
|
+
|
|
9
|
+
Rewrites the plugin internals to drop deprecated ESLint APIs, effectively making
|
|
10
|
+
it ESLint 10 compatible.
|
|
11
|
+
|
|
12
|
+
## 24.0.0
|
|
13
|
+
|
|
14
|
+
### Major Changes
|
|
15
|
+
|
|
16
|
+
- 2defaab: Remove two Vue 2 slot rules from the `vue` config and from the plugin.
|
|
17
|
+
|
|
18
|
+
- `@gitlab/vue-prefer-dollar-scopedslots` is removed. It told authors to use `$scopedSlots`, which
|
|
19
|
+
Vue 3 does not have. Under `@vue/compat` every access is a deprecation, and eslint-plugin-vue's
|
|
20
|
+
`vue/no-deprecated-dollar-scopedslots-api` reports it. A consumer that still wants to forbid
|
|
21
|
+
`$slots` can do so with `vue/no-restricted-syntax`.
|
|
22
|
+
- `@gitlab/vue-slot-name-casing` is removed. The `vue` config now enables
|
|
23
|
+
`vue/slot-name-casing` with `kebab-case`, which checks the same `<slot name>` attribute.
|
|
24
|
+
|
|
25
|
+
Consumers that reference either rule by name, for example in an `eslint-disable` comment, must
|
|
26
|
+
drop the reference.
|
|
27
|
+
|
|
3
28
|
## 23.0.0
|
|
4
29
|
|
|
5
30
|
### Major Changes
|
package/docs/rules.md
CHANGED
|
@@ -18,11 +18,9 @@ Available rules:
|
|
|
18
18
|
- [vue-no-new-non-primitive-in-template](./rules/vue-no-new-non-primitive-in-template.md): Prevents non-primitive values from being declared in templates
|
|
19
19
|
- [vue-no-popover-target-dollar-el](./rules/vue-no-popover-target-dollar-el.md): Disallow function-form `:target` bindings ending in `.$el` on `<gl-popover>` and `<gl-tooltip>`
|
|
20
20
|
- [vue-no-undef-apollo-properties](./rules/vue-no-undef-apollo-properties.md): Require Apollo query properties to be initialized in component data.
|
|
21
|
-
- [vue-prefer-dollar-scopedslots](./rules/vue-prefer-dollar-scopedslots.md): Prefer $scopedSlots over $slots for Vue 2.x.
|
|
22
21
|
- [vue-require-i18n-attribute-strings](./rules/vue-require-i18n-attribute-strings.md): Detect non externalized strings in vue `<template>` attributes
|
|
23
22
|
- [vue-require-i18n-strings](./rules/vue-require-i18n-strings.md): enforce no bare strings in vue `<template>`
|
|
24
23
|
- [vue-require-required-key](./rules/vue-require-required-key.md): Require the required key to be set
|
|
25
24
|
- [vue-require-valid-i18n-helpers](./rules/vue-require-valid-i18n-helpers.md): Enforces valid usage of translation helpers in Vue templates.
|
|
26
|
-
- [vue-slot-name-casing](./rules/vue-slot-name-casing.md): enforce specific casing for slot naming style in template
|
|
27
25
|
- [vue-tailwind-no-interpolation](./rules/vue-tailwind-no-interpolation.md): Prevents building Tailwind CSS utility classes with string interpolation.
|
|
28
26
|
- [vue-tailwind-no-max-width-media-queries](./rules/vue-tailwind-no-max-width-media-queries.md): Prevents the usage of max-width media query Tailwind CSS utility classes.
|
package/lib/plugin.js
CHANGED
|
@@ -20,12 +20,10 @@ module.exports = {
|
|
|
20
20
|
'vue-no-new-non-primitive-in-template': require('./rules/vue-no-new-non-primitive-in-template.js'),
|
|
21
21
|
'vue-no-popover-target-dollar-el': require('./rules/vue-no-popover-target-dollar-el.js'),
|
|
22
22
|
'vue-no-undef-apollo-properties': require('./rules/vue-no-undef-apollo-properties.js'),
|
|
23
|
-
'vue-prefer-dollar-scopedslots': require('./rules/vue-prefer-dollar-scopedslots.js'),
|
|
24
23
|
'vue-require-i18n-attribute-strings': require('./rules/vue-require-i18n-attribute-strings.js'),
|
|
25
24
|
'vue-require-i18n-strings': require('./rules/vue-require-i18n-strings.js'),
|
|
26
25
|
'vue-require-required-key': require('./rules/vue-require-required-key.js'),
|
|
27
26
|
'vue-require-valid-i18n-helpers': require('./rules/vue-require-valid-i18n-helpers.js'),
|
|
28
|
-
'vue-slot-name-casing': require('./rules/vue-slot-name-casing.js'),
|
|
29
27
|
'vue-tailwind-no-interpolation': require('./rules/vue-tailwind-no-interpolation.js'),
|
|
30
28
|
'vue-tailwind-no-max-width-media-queries': require('./rules/vue-tailwind-no-max-width-media-queries.js'),
|
|
31
29
|
},
|
package/lib/vue-fragments.js
CHANGED
|
@@ -63,8 +63,7 @@ const gitlabRules = [
|
|
|
63
63
|
'vue/v-slot-style': ['error', { atComponent: 'shorthand' }],
|
|
64
64
|
'@gitlab/vue-no-data-toggle': 'error',
|
|
65
65
|
'@gitlab/vue-no-popover-target-dollar-el': 'warn',
|
|
66
|
-
'
|
|
67
|
-
'@gitlab/vue-slot-name-casing': 'error',
|
|
66
|
+
'vue/slot-name-casing': ['error', 'kebab-case'],
|
|
68
67
|
'@gitlab/no-runtime-template-compiler': 'error',
|
|
69
68
|
'import-x/order': [
|
|
70
69
|
'error',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/eslint-plugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "24.1.0",
|
|
4
4
|
"description": "GitLab package for our custom eslint rules",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"node": "^20.12.0 || ^22.0.0 || >=24.0.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@eslint/js": "^
|
|
34
|
+
"@eslint/js": "^10.0.1",
|
|
35
35
|
"eslint-config-prettier": "^10.0.0",
|
|
36
36
|
"eslint-plugin-import-x": "^4.17.1",
|
|
37
37
|
"eslint-plugin-jest": "^29.0.0",
|
|
38
|
-
"eslint-plugin-promise": "^7.
|
|
38
|
+
"eslint-plugin-promise": "^7.3.0",
|
|
39
39
|
"eslint-plugin-tailwindcss": "^3.18.3",
|
|
40
40
|
"eslint-plugin-unicorn": "^55.0.0",
|
|
41
41
|
"eslint-plugin-vue": "^10.0.0",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"vue-eslint-parser": "^10.3.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
49
|
-
"@typescript-eslint/parser": "^8.
|
|
50
|
-
"eslint": "^9.0.0",
|
|
48
|
+
"@typescript-eslint/eslint-plugin": "^8.70.1",
|
|
49
|
+
"@typescript-eslint/parser": "^8.70.1",
|
|
50
|
+
"eslint": "^9.0.0 || ^10.0.0",
|
|
51
51
|
"typescript": ">=4.8.4"
|
|
52
52
|
},
|
|
53
53
|
"peerDependenciesMeta": {
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@changesets/cli": "^2.29.8",
|
|
66
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
67
|
-
"@typescript-eslint/parser": "^8.
|
|
68
|
-
"eslint": "^
|
|
66
|
+
"@typescript-eslint/eslint-plugin": "^8.70.1",
|
|
67
|
+
"@typescript-eslint/parser": "^8.70.1",
|
|
68
|
+
"eslint": "^10.11.0",
|
|
69
69
|
"glob": "^7.2.0",
|
|
70
70
|
"mocha": "^11.7.5",
|
|
71
71
|
"prettier": "^2.6.1",
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# @gitlab/vue-prefer-dollar-scopedslots
|
|
2
|
-
|
|
3
|
-
Prefer $scopedSlots over $slots when using Vue 2.x.
|
|
4
|
-
|
|
5
|
-
Scoped slots are more flexible and powerful, ease migration to Vue 3.x, and
|
|
6
|
-
also work around https://github.com/vuejs/vue/issues/11084.
|
|
7
|
-
|
|
8
|
-
This rule should _not_ be used with Vue 3.x, since `$scopedSlots` was
|
|
9
|
-
[removed](https://v3-migration.vuejs.org/breaking-changes/slots-unification.html).
|
|
10
|
-
Instead, use
|
|
11
|
-
[`vue/no-deprecated-dollar-scopedslots-api`](https://eslint.vuejs.org/rules/no-deprecated-dollar-scopedslots-api.html).
|
|
12
|
-
It includes a fixer that will migrate `$scopedSlots` usage _back_ to `$slots`,
|
|
13
|
-
which is trivial since the API for Vue 2.x's `$scopedSlots` is identical to Vue
|
|
14
|
-
3.x's `$slots`.
|
|
15
|
-
|
|
16
|
-
## Rule Details
|
|
17
|
-
|
|
18
|
-
### Examples of **incorrect** code for this rule
|
|
19
|
-
|
|
20
|
-
```html
|
|
21
|
-
<div v-if="$slots.default">
|
|
22
|
-
<slot></slot>
|
|
23
|
-
</div>
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
```javascript
|
|
27
|
-
export default {
|
|
28
|
-
render(h) {
|
|
29
|
-
return this.$slots.foo ? this.$slots.foo : null;
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Examples of **correct** code for this rule
|
|
35
|
-
|
|
36
|
-
```html
|
|
37
|
-
<div v-if="$scopedSlots.default">
|
|
38
|
-
<slot></slot>
|
|
39
|
-
</div>
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
```javascript
|
|
43
|
-
export default {
|
|
44
|
-
render(h) {
|
|
45
|
-
return this.$scopedSlots.foo
|
|
46
|
-
? this.$scopedSlots.foo() // Note the function call!
|
|
47
|
-
: null;
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Options
|
|
53
|
-
|
|
54
|
-
Nothing
|
|
55
|
-
|
|
56
|
-
## Related rules
|
|
57
|
-
|
|
58
|
-
- [`vue/no-deprecated-dollar-scopedslots-api`](https://eslint.vuejs.org/rules/no-deprecated-dollar-scopedslots-api.html) (for Vue 3.x)
|
|
59
|
-
|
|
60
|
-
## When Not To Use It
|
|
61
|
-
|
|
62
|
-
When using Vue 3.x.
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# @gitlab/vue-slot-name-casing
|
|
2
|
-
|
|
3
|
-
Ensures that slot names are kebab-cased
|
|
4
|
-
|
|
5
|
-
## Rule Details
|
|
6
|
-
|
|
7
|
-
### Examples of **incorrect** code for this rule
|
|
8
|
-
|
|
9
|
-
```html
|
|
10
|
-
<slot name="filepathPrepend"></slot>
|
|
11
|
-
<slot name="filepathPrepend"></slot>
|
|
12
|
-
<slot name="filepathPrepend"></slot>
|
|
13
|
-
<div>
|
|
14
|
-
<template #filepathPrepend
|
|
15
|
-
>example</template
|
|
16
|
-
>
|
|
17
|
-
</div>
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### Examples of **correct** code for this rule
|
|
21
|
-
|
|
22
|
-
```html
|
|
23
|
-
<slot name="filepath-prepend"></slot>
|
|
24
|
-
<slot name="filepath-prepend"></slot>
|
|
25
|
-
<slot name="filepath-prepend"></slot>
|
|
26
|
-
<div>
|
|
27
|
-
<template #filepath-prepend
|
|
28
|
-
>example</template
|
|
29
|
-
>
|
|
30
|
-
</div>
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Options
|
|
34
|
-
|
|
35
|
-
No options
|
|
36
|
-
|
|
37
|
-
## Related rules
|
|
38
|
-
|
|
39
|
-
- TBA
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// ------------------------------------------------------------------------------
|
|
2
|
-
// Requirements
|
|
3
|
-
// ------------------------------------------------------------------------------
|
|
4
|
-
|
|
5
|
-
const { DOCS_BASE_URL } = require('../constants');
|
|
6
|
-
const { defineTemplateBodyVisitor } = require('../utils/index');
|
|
7
|
-
const utils = require('eslint-plugin-vue/dist/utils').default;
|
|
8
|
-
|
|
9
|
-
// ------------------------------------------------------------------------------
|
|
10
|
-
// Helpers
|
|
11
|
-
// ------------------------------------------------------------------------------
|
|
12
|
-
|
|
13
|
-
const DOLLAR_SLOTS = '$slots';
|
|
14
|
-
|
|
15
|
-
// ------------------------------------------------------------------------------
|
|
16
|
-
// Rule Definition
|
|
17
|
-
// ------------------------------------------------------------------------------
|
|
18
|
-
|
|
19
|
-
module.exports = {
|
|
20
|
-
meta: {
|
|
21
|
-
type: 'error',
|
|
22
|
-
docs: {
|
|
23
|
-
description: 'Prefer $scopedSlots over $slots for Vue 2.x.',
|
|
24
|
-
category: undefined,
|
|
25
|
-
url: DOCS_BASE_URL + '/vue-prefer-dollar-scopedslots.md',
|
|
26
|
-
},
|
|
27
|
-
messages: {
|
|
28
|
-
preferDollarScopedSlots:
|
|
29
|
-
'Prefer $scopedSlots over $slots for Vue 2.x. Scoped slots are more flexible and powerful, ease migration to Vue 3.x, and also work around https://github.com/vuejs/vue/issues/11084.',
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
create(context) {
|
|
33
|
-
const templateVisitor = {
|
|
34
|
-
VExpressionContainer(node) {
|
|
35
|
-
for (const ref of node.references) {
|
|
36
|
-
if (ref.id.name === DOLLAR_SLOTS) {
|
|
37
|
-
context.report({
|
|
38
|
-
node,
|
|
39
|
-
loc: ref.id.loc,
|
|
40
|
-
messageId: 'preferDollarScopedSlots',
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const scriptVisitor = utils.defineVueVisitor(context, {
|
|
48
|
-
MemberExpression(node) {
|
|
49
|
-
if (node.computed) return;
|
|
50
|
-
|
|
51
|
-
const { property } = node;
|
|
52
|
-
if (property.name === DOLLAR_SLOTS) {
|
|
53
|
-
context.report({
|
|
54
|
-
node: property,
|
|
55
|
-
loc: property.loc,
|
|
56
|
-
messageId: 'preferDollarScopedSlots',
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor);
|
|
63
|
-
},
|
|
64
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// ------------------------------------------------------------------------------
|
|
4
|
-
// Requirements
|
|
5
|
-
// ------------------------------------------------------------------------------
|
|
6
|
-
|
|
7
|
-
const utils = require('eslint-plugin-vue/dist/utils').default;
|
|
8
|
-
const casing = require('eslint-plugin-vue/dist/utils/casing');
|
|
9
|
-
const { DOCS_BASE_URL } = require('../constants');
|
|
10
|
-
|
|
11
|
-
// ------------------------------------------------------------------------------
|
|
12
|
-
// Rule Definition
|
|
13
|
-
// ------------------------------------------------------------------------------
|
|
14
|
-
|
|
15
|
-
module.exports = {
|
|
16
|
-
meta: {
|
|
17
|
-
type: 'suggestion',
|
|
18
|
-
docs: {
|
|
19
|
-
description: 'enforce specific casing for slot naming style in template',
|
|
20
|
-
category: undefined,
|
|
21
|
-
url: DOCS_BASE_URL + '/vue-slot-name-casing.md',
|
|
22
|
-
},
|
|
23
|
-
schema: [],
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
create(context) {
|
|
27
|
-
const caseType = 'kebab-case';
|
|
28
|
-
|
|
29
|
-
let hasInvalidEOF = false;
|
|
30
|
-
|
|
31
|
-
return utils.defineTemplateBodyVisitor(
|
|
32
|
-
context,
|
|
33
|
-
{
|
|
34
|
-
"VElement[name='slot'] > VStartTag > VAttribute[key.name='name']"(node) {
|
|
35
|
-
if (hasInvalidEOF) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const name = node.value.value;
|
|
40
|
-
const casingName = casing.getConverter(caseType)(name);
|
|
41
|
-
if (casingName !== name) {
|
|
42
|
-
context.report({
|
|
43
|
-
node,
|
|
44
|
-
loc: node.loc,
|
|
45
|
-
message: 'Slot name "{{name}}" is not {{caseType}}.',
|
|
46
|
-
data: {
|
|
47
|
-
name,
|
|
48
|
-
caseType,
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
Object.assign(
|
|
55
|
-
{
|
|
56
|
-
Program(node) {
|
|
57
|
-
hasInvalidEOF = utils.hasInvalidEOF(node);
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
{},
|
|
61
|
-
),
|
|
62
|
-
);
|
|
63
|
-
},
|
|
64
|
-
};
|