@gitlab/eslint-plugin 21.4.1 → 22.0.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 +223 -0
- package/README.md +16 -11
- package/docs/development.md +2 -1
- package/docs/rules/vue-no-popover-target-dollar-el.md +69 -0
- package/docs/rules.md +1 -0
- package/docs/usage.md +158 -47
- package/eslint9/index.js +6 -7
- package/lib/configs/base/best-practices.js +0 -4
- package/lib/configs/base/es6.js +0 -12
- package/lib/configs/base/imports.js +0 -9
- package/lib/configs/base/node.js +0 -4
- package/lib/confusing-browser-globals.js +68 -0
- package/lib/flat-configs/base.js +122 -0
- package/lib/flat-configs/default.js +13 -0
- package/lib/flat-configs/i18n.js +14 -0
- package/lib/flat-configs/jest.js +20 -0
- package/lib/flat-configs/tailwind.js +19 -0
- package/{eslint9/configs → lib/flat-configs}/typescript.js +47 -62
- package/lib/flat-configs/vue.js +16 -0
- package/lib/index.js +30 -38
- package/lib/plugin.js +32 -0
- package/lib/prettier-rules.js +10 -0
- package/lib/rules/no-runtime-template-compiler.js +5 -2
- package/lib/rules/vue-no-new-non-primitive-in-template.js +1 -1
- package/lib/rules/vue-no-popover-target-dollar-el.js +156 -0
- package/lib/rules/vue-no-undef-apollo-properties.js +1 -1
- package/lib/rules/vue-prefer-dollar-scopedslots.js +1 -1
- package/lib/rules/vue-require-required-key.js +1 -1
- package/lib/rules/vue-slot-name-casing.js +2 -2
- package/lib/vue-fragments.js +111 -0
- package/package.json +29 -11
- package/scripts/generateRuleMapFixtures.js +75 -0
- package/scripts/helpers/getConfigs.js +13 -6
- package/scripts/integration_test/bootstrap.sh +1 -1
- package/scripts/updateFiles.js +30 -6
- package/eslint9/configs/base.js +0 -140
- package/lib/configs/base.js +0 -115
- package/lib/configs/default.js +0 -17
- package/lib/configs/i18n.js +0 -10
- package/lib/configs/jest.js +0 -21
- package/lib/configs/tailwind.js +0 -10
- package/lib/configs/typescript.js +0 -95
- package/lib/configs/vue.js +0 -90
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,228 @@
|
|
|
1
1
|
# @gitlab/eslint-plugin
|
|
2
2
|
|
|
3
|
+
## 22.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 5c9ebc5: Migrate to ESLint 9 flat config.
|
|
8
|
+
|
|
9
|
+
Every config this package exports is now an array of flat config objects, meant to be spread into
|
|
10
|
+
an `eslint.config.js`. The eslintrc configs have been removed. `docs/usage.md` has the new examples
|
|
11
|
+
and a table mapping each old `extends` entry to its replacement.
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
15
|
+
|
|
16
|
+
module.exports = [...gitlab.configs.default];
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## If you use the `typescript` config, read this first
|
|
20
|
+
|
|
21
|
+
**Your `.ts` files were not being parsed as TypeScript before this release, and now they are.**
|
|
22
|
+
`lib/configs/typescript.js` set `parserOptions.parser: '@typescript-eslint/parser'` inside an
|
|
23
|
+
`overrides` block, and eslintrc ignores that key — only a `parser` key selects a parser. The flat
|
|
24
|
+
config sets `languageOptions.parser`, correctly. So `.ts` files are now genuinely parsed as
|
|
25
|
+
TypeScript, the type-aware rules in the config (`@typescript-eslint/no-floating-promises`,
|
|
26
|
+
`@typescript-eslint/return-await`, the `strict` preset) start doing real work for the first time,
|
|
27
|
+
and you should expect a wave of new findings on code that has not changed. Budget for that before
|
|
28
|
+
you upgrade. Nothing in the rule configuration changed to cause it; the rules were always listed,
|
|
29
|
+
they just had nothing to analyse.
|
|
30
|
+
|
|
31
|
+
Relatedly, the `typescript` config could not be installed from a clean install: it needs
|
|
32
|
+
`typescript` and `@typescript-eslint/parser` to load `@typescript-eslint/eslint-plugin`, and neither
|
|
33
|
+
was declared, so it only worked because the README told you to install them yourself. All three are
|
|
34
|
+
now declared optional peer dependencies. Install them in your own project and your package manager
|
|
35
|
+
will resolve them:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
yarn add --dev typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The `overrides` block the README used to ask for is no longer needed and can be deleted.
|
|
42
|
+
|
|
43
|
+
## Breaking changes
|
|
44
|
+
|
|
45
|
+
### Config format and surface
|
|
46
|
+
|
|
47
|
+
1. **The seven eslintrc configs are gone.** Every `extends: ['plugin:@gitlab/*']` in an `.eslintrc`
|
|
48
|
+
stops resolving. Move to `eslint.config.js` and spread the array of the same name:
|
|
49
|
+
`...gitlab.configs.default`, `...gitlab.configs.vue`, and so on.
|
|
50
|
+
2. **The eight `base` fragments are no longer exported as configs** — `best-practices`, `errors`,
|
|
51
|
+
`es6`, `imports`, `node`, `strict`, `style` and `variables`. This is separate from the point
|
|
52
|
+
above: it hits anyone who extended a fragment directly rather than extending `base`. The files
|
|
53
|
+
are still in the package; only the public config surface shrinks. Use `base`.
|
|
54
|
+
3. **Config values changed shape.** Each config is now an array of flat config objects, not a single
|
|
55
|
+
eslintrc object. Code that read `configs.base.rules` or merged a config into another object needs
|
|
56
|
+
to work with the array instead.
|
|
57
|
+
4. **`configs` entries are lazy getters.** This keeps `require('@gitlab/eslint-plugin')` from
|
|
58
|
+
loading the optional TypeScript packages for consumers who do not use them. `Object.keys` and
|
|
59
|
+
`for...in` still list all seven names, but anything that _reads_ every entry at once —
|
|
60
|
+
`{ ...plugin.configs }`, a deep clone, `JSON.stringify` — invokes all seven getters and throws if
|
|
61
|
+
the TypeScript packages are absent. `Object.getOwnPropertyDescriptor(configs, name).value` is now
|
|
62
|
+
`undefined` where it used to be the config. Read configs by name.
|
|
63
|
+
5. **Deep subpath imports no longer resolve.** The package has no `exports` map, so every path in
|
|
64
|
+
the tarball used to be importable. The files behind those paths were deleted, so
|
|
65
|
+
`@gitlab/eslint-plugin/lib/configs/vue` and `@gitlab/eslint-plugin/eslint9/configs/base` now
|
|
66
|
+
throw `MODULE_NOT_FOUND`. Import from the package root. The `/eslint9` subpath itself still
|
|
67
|
+
resolves.
|
|
68
|
+
6. **`@gitlab/eslint-plugin/eslint9` is now the full package root**, not
|
|
69
|
+
`{ configs: { base, typescript } }`. It re-exports everything the root does, so existing imports
|
|
70
|
+
keep working, and it is deprecated — switch to `@gitlab/eslint-plugin`. It is scheduled for
|
|
71
|
+
removal in a future major release.
|
|
72
|
+
7. **`plugin.meta` now exists** (`{ name, version }`). Additive, and it is what makes the plugin
|
|
73
|
+
registerable in a flat config; ESLint uses it for cache keys and error attribution.
|
|
74
|
+
|
|
75
|
+
### Requirements and dependencies
|
|
76
|
+
|
|
77
|
+
- **`eslint` is now a `^9.0.0` peer dependency.** ESLint 8 is no longer supported.
|
|
78
|
+
- **`engines.node` is now `^20.12.0 || ^22.0.0 || >=24.0.0`.** This drops Node 18 and the
|
|
79
|
+
odd-numbered lines. It is the intersection of every runtime dependency's own `engines`,
|
|
80
|
+
and is set by `eslint-plugin-jest` 29 rather than by ESLint 9, which is more permissive
|
|
81
|
+
(`^18.18.0 || ^20.9.0 || >=21.1.0`).
|
|
82
|
+
- **`@typescript-eslint/eslint-plugin`, `@typescript-eslint/parser` and `typescript` moved from
|
|
83
|
+
dependencies to optional peer dependencies.** Only consumers of the `typescript` config need them,
|
|
84
|
+
and those consumers now control the versions. See the section above.
|
|
85
|
+
- **`eslint-plugin-vue` is bumped to `^10.0.0`.** `vue/component-tags-order` was removed upstream
|
|
86
|
+
and is configured here as `vue/block-order` with the same options. If your project overrides
|
|
87
|
+
`vue/component-tags-order`, rename it: configuring a rule a plugin no longer defines is a hard
|
|
88
|
+
error in flat config, so ESLint refuses to run rather than ignoring it.
|
|
89
|
+
- **`vue-eslint-parser` is bumped to `^10.3.0`, `eslint-plugin-jest` to `^29.0.0`, and
|
|
90
|
+
`eslint-config-prettier` to `^10.0.0`.** Each brings its own upstream preset changes.
|
|
91
|
+
- **`@typescript-eslint/no-throw-literal` is configured as `@typescript-eslint/only-throw-error`**,
|
|
92
|
+
following the rename in `@typescript-eslint` v8.
|
|
93
|
+
|
|
94
|
+
### ESLint 9 defaults
|
|
95
|
+
|
|
96
|
+
Two core rules report less than they did under ESLint 8:
|
|
97
|
+
|
|
98
|
+
- `no-constant-condition` no longer reports `while (true)`.
|
|
99
|
+
- `no-inner-declarations` no longer reports block-scoped function declarations.
|
|
100
|
+
|
|
101
|
+
`no-fallthrough`, `no-useless-escape` and `no-unused-expressions` gained new options in ESLint 9,
|
|
102
|
+
but their defaults preserve ESLint 8 behaviour, so nothing changes for them unless you opt in.
|
|
103
|
+
|
|
104
|
+
One flat-config default reports **more**. ESLint 9 defaults
|
|
105
|
+
`linterOptions.reportUnusedDisableDirectives` to `warn`, where eslintrc left unused directives
|
|
106
|
+
unreported unless you passed `--report-unused-disable-directives`. Every stale
|
|
107
|
+
`// eslint-disable` comment in your project — including ones made stale by the rule changes listed
|
|
108
|
+
below — now produces a warning. This is ESLint's default and not something this package sets, but
|
|
109
|
+
it is a new source of warnings on unchanged code, and it will fail a build that runs
|
|
110
|
+
`eslint --max-warnings 0`. `eslint --fix` removes the directives; alternatively set
|
|
111
|
+
`linterOptions: { reportUnusedDisableDirectives: 'off' }` in a config object of your own.
|
|
112
|
+
|
|
113
|
+
### What stops being caught
|
|
114
|
+
|
|
115
|
+
Most of the churn below is substitution: a rule is renamed, split or superseded, and the same code
|
|
116
|
+
is still reported by its replacement. These are the reductions where nothing in this package takes
|
|
117
|
+
over.
|
|
118
|
+
|
|
119
|
+
| No longer reported | Configs | Picked up by |
|
|
120
|
+
| ------------------------------------------------ | ------- | ------------ |
|
|
121
|
+
| `while (true)` | all | nothing |
|
|
122
|
+
| a function declaration inside a block | all | nothing |
|
|
123
|
+
| assigning to a class binding (`no-class-assign`) | `.ts` | `tsc` |
|
|
124
|
+
| `with (obj) {}` (`no-with`) | `.ts` | `tsc` |
|
|
125
|
+
| stray semicolons, mixed spaces and tabs | `.ts` | prettier |
|
|
126
|
+
|
|
127
|
+
The first two are the ESLint 9 default changes described above; they apply to every config. The
|
|
128
|
+
other three are only switched off for TypeScript files, by `@typescript-eslint` v8 and by ESLint 9
|
|
129
|
+
dropping two deprecated formatting rules from `eslint:recommended`.
|
|
130
|
+
|
|
131
|
+
Separately, and in the other direction: `vue/jsx-uses-vars` no longer applies outside `.vue` files.
|
|
132
|
+
It suppresses `no-unused-vars` for identifiers used only in JSX, so if you enable JSX in your own
|
|
133
|
+
config you may see new false `no-unused-vars` reports. Re-enable the rule yourself if so. These
|
|
134
|
+
configs never enabled JSX, so nothing changes unless you did.
|
|
135
|
+
|
|
136
|
+
### Rules whose severity changes
|
|
137
|
+
|
|
138
|
+
25 rules change in a severity-visible way: they turn on, turn off, or are replaced by a differently
|
|
139
|
+
named rule. Everything else resolves to the same severity it did before. The causes are the
|
|
140
|
+
dependency majors listed above — none of these are a change of intent by this package.
|
|
141
|
+
|
|
142
|
+
**`vue` and `default` — 5 rules.** These hit the widest audience:
|
|
143
|
+
|
|
144
|
+
- `vue/component-tags-order` (`error`) is **gone**, replaced by `vue/block-order` (`error`) with
|
|
145
|
+
the same `{ order }` option. Rename any override you have; see the note above on why a stale
|
|
146
|
+
override is a hard error rather than a no-op.
|
|
147
|
+
- `vue/no-required-prop-with-default` is **newly on at `warn`**. eslint-plugin-vue v10 added it to
|
|
148
|
+
the recommended presets. It fires on ordinary, unchanged Vue 2 code, and because it is a warning
|
|
149
|
+
rather than an error it will **fail any build running `eslint --max-warnings 0`** while passing a
|
|
150
|
+
plain `eslint` run. If that describes your CI, expect this one to break it. Either fix the props
|
|
151
|
+
it flags or set `'vue/no-required-prop-with-default': 'off'` in your own config.
|
|
152
|
+
- `vue/comment-directive` and `vue/jsx-uses-vars` **no longer apply outside `.vue` files**.
|
|
153
|
+
eslint-plugin-vue v10 scopes both to `**/*.vue`, where v9 declared them for every linted file. No
|
|
154
|
+
coverage is lost: `vue/comment-directive` only ever acts on single-file-component output, and
|
|
155
|
+
`vue/jsx-uses-vars` needs `parserOptions.ecmaFeatures.jsx`, which these configs never enabled.
|
|
156
|
+
|
|
157
|
+
**`typescript`, on `.ts` and `.test.ts` files — 20 rules.** These arrive from ESLint 9's
|
|
158
|
+
`eslint:recommended` and from `@typescript-eslint` v8's `strict` preset, which only this config
|
|
159
|
+
extends. Note that they land on top of the parsing change described at the top of this changeset,
|
|
160
|
+
so a `typescript` consumer should expect new findings from both at once.
|
|
161
|
+
|
|
162
|
+
Newly reporting at `error`:
|
|
163
|
+
|
|
164
|
+
- From ESLint 9's `eslint:recommended`: `no-constant-binary-expression`, `no-empty-static-block`,
|
|
165
|
+
`no-unused-private-class-members`.
|
|
166
|
+
- From `@typescript-eslint` v8 dropping the extension-rule pair, so the core rule takes over:
|
|
167
|
+
`no-loss-of-precision`.
|
|
168
|
+
- From the `ban-types` split: `@typescript-eslint/no-empty-object-type`,
|
|
169
|
+
`@typescript-eslint/no-unsafe-function-type`, `@typescript-eslint/no-wrapper-object-types`.
|
|
170
|
+
- Replacing a dropped or renamed rule: `@typescript-eslint/no-require-imports` (for
|
|
171
|
+
`no-var-requires`), `@typescript-eslint/only-throw-error` (for `no-throw-literal`),
|
|
172
|
+
`@typescript-eslint/no-unused-expressions` (for the core rule).
|
|
173
|
+
- Moved into `recommended`, and so into `strict`, by `@typescript-eslint` v8:
|
|
174
|
+
`@typescript-eslint/prefer-namespace-keyword`.
|
|
175
|
+
|
|
176
|
+
No longer reporting — switched off, or removed from the rule set entirely:
|
|
177
|
+
|
|
178
|
+
- Dropped from `eslint:recommended` in ESLint 9, and already switched off by
|
|
179
|
+
`eslint-config-prettier` earlier in the chain, so they stay off: `no-extra-semi`,
|
|
180
|
+
`no-mixed-spaces-and-tabs`. Both are deprecated formatting rules that prettier enforces anyway.
|
|
181
|
+
- Added to `@typescript-eslint` v8's `eslint-recommended` layer, on the grounds that the TypeScript
|
|
182
|
+
compiler already reports them: `no-class-assign`, `no-with`.
|
|
183
|
+
- Superseded by the TypeScript-aware rule named above: `no-unused-expressions`.
|
|
184
|
+
- Removed from the `@typescript-eslint` v8 rule set or dropped from its `strict` preset:
|
|
185
|
+
`@typescript-eslint/ban-types`, `@typescript-eslint/no-var-requires`,
|
|
186
|
+
`@typescript-eslint/no-loss-of-precision`, `@typescript-eslint/no-throw-literal`.
|
|
187
|
+
|
|
188
|
+
The `base`, `jest`, `i18n` and `tailwind` configs have no severity changes at all.
|
|
189
|
+
|
|
190
|
+
### `@stylistic` rules are not disabled for you
|
|
191
|
+
|
|
192
|
+
`eslint-config-prettier` v10 added 180 `@stylistic/*` entries to the formatting rules it switches
|
|
193
|
+
off. This package strips them before shipping, because it does not register the `@stylistic`
|
|
194
|
+
plugin and configuring a rule for an unregistered plugin is a hard error in flat config. So if you
|
|
195
|
+
register `@stylistic` yourself, **you do not get prettier's `@stylistic` disables from this
|
|
196
|
+
package** and its formatting rules may conflict with prettier. Apply `eslint-config-prettier` in
|
|
197
|
+
your own config, after the GitLab configs, to switch them off.
|
|
198
|
+
|
|
199
|
+
## What has not changed
|
|
200
|
+
|
|
201
|
+
**The Vue rules still target Vue 2.** `eslint-plugin-vue` v9's `configs.recommended` resolved to the
|
|
202
|
+
Vue 2 preset, and this release deliberately maps it to v10's `flat/vue2-recommended` rather than
|
|
203
|
+
v10's `flat/recommended`, which is Vue 3. Retargeting would have added 33 rules and removed 6, which
|
|
204
|
+
is a product decision rather than something to fold into a config-format migration. Vue rule
|
|
205
|
+
coverage is unchanged in this release; a deliberate Vue 3 retarget is planned for a later one.
|
|
206
|
+
|
|
207
|
+
**No rule set was changed on purpose.** The migration is gated on frozen rule-map fixtures captured
|
|
208
|
+
from the eslintrc configs before any of this work started, and every difference between those
|
|
209
|
+
fixtures and what the flat configs resolve to is recorded and justified in the repository. The 25
|
|
210
|
+
rules listed under "Rules whose severity changes" above are the complete set of severity-visible
|
|
211
|
+
differences; the rest are ESLint 9 rendering the same configured options differently, which changes
|
|
212
|
+
no behaviour.
|
|
213
|
+
|
|
214
|
+
## New
|
|
215
|
+
|
|
216
|
+
- Flat configs for all seven config names: `base`, `default`, `vue`, `jest`, `i18n`, `tailwind` and
|
|
217
|
+
`typescript`. Previously only `base` and `typescript` had flat equivalents, under
|
|
218
|
+
`@gitlab/eslint-plugin/eslint9`.
|
|
219
|
+
|
|
220
|
+
## 21.5.0
|
|
221
|
+
|
|
222
|
+
### Minor Changes
|
|
223
|
+
|
|
224
|
+
- 8fa643e: Add `vue-no-popover-target-dollar-el` rule to flag and autofix unnecessary `.$el` in `:target` callbacks on `<gl-popover>` and `<gl-tooltip>`.
|
|
225
|
+
|
|
3
226
|
## 21.4.1
|
|
4
227
|
|
|
5
228
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -21,22 +21,27 @@ upstream later.
|
|
|
21
21
|
- [Installation and Usage](./docs/usage.md)
|
|
22
22
|
- [Creation & Development of rules](./docs/development.md)
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## Requirements
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
- ESLint 9 (`^9.0.0`), configured with [flat config](https://eslint.org/docs/latest/use/configure/configuration-files) (`eslint.config.js`)
|
|
27
|
+
- Node.js `^18.18.0 || ^20.9.0 || >=21.1.0`
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
Every config this package exports is a flat config array:
|
|
29
30
|
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"@typescript-eslint/parser": "^8.38.0"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
31
|
+
```js
|
|
32
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
33
|
+
|
|
34
|
+
module.exports = [...gitlab.configs.default];
|
|
37
35
|
```
|
|
38
36
|
|
|
39
|
-
(
|
|
37
|
+
The eslintrc configs (`extends: ['plugin:@gitlab/default']`) were removed in this major release.
|
|
38
|
+
See [Installation and Usage](./docs/usage.md#migrating-from-the-eslintrc-configs) for the
|
|
39
|
+
migration.
|
|
40
|
+
|
|
41
|
+
Using the `typescript` config additionally requires `@typescript-eslint/parser`,
|
|
42
|
+
`@typescript-eslint/eslint-plugin` and `typescript` in your own project. They are optional peer
|
|
43
|
+
dependencies, so your project controls their versions — the `overrides` workaround this README used
|
|
44
|
+
to document is no longer needed.
|
|
40
45
|
|
|
41
46
|
## Contribution guidelines
|
|
42
47
|
|
package/docs/development.md
CHANGED
|
@@ -8,7 +8,8 @@ Always `yarn install` before doing things.
|
|
|
8
8
|
a [lefthook](https://github.com/Arkweid/lefthook) `pre-commit` hook.
|
|
9
9
|
2. This project adheres to semantic commits,
|
|
10
10
|
use a tool like [git-cz](https://www.npmjs.com/package/git-cz) to write commit messages
|
|
11
|
-
3. There is a script `yarn update` which
|
|
11
|
+
3. There is a script `yarn update` which regenerates `lib/plugin.js` (the rule map),
|
|
12
|
+
`lib/index.js` (the config getters) and `docs/rules.md` (the rule index),
|
|
12
13
|
please run it after creating or updating rules.
|
|
13
14
|
|
|
14
15
|
## Creating rules
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @gitlab/vue-no-popover-target-dollar-el
|
|
2
|
+
|
|
3
|
+
Disallows function-form `:target` bindings on `<gl-popover>` and `<gl-tooltip>` where
|
|
4
|
+
the callback body ends in `.$el`.
|
|
5
|
+
|
|
6
|
+
`GlPopover` and `GlTooltip` accept a `:target` prop that is either a reference or a
|
|
7
|
+
zero-argument function returning one. The reference can be a plain DOM element
|
|
8
|
+
[or a Vue component instance](https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/merge_requests/6006).
|
|
9
|
+
The components use `.$el` automatically when it exists, so accessing it
|
|
10
|
+
manually is unnecessary. This helps to avoid reference errors during teardown,
|
|
11
|
+
or other cases where the ref does not exist at the time the `target` function
|
|
12
|
+
is called.
|
|
13
|
+
|
|
14
|
+
## Rule Details
|
|
15
|
+
|
|
16
|
+
### Examples of **incorrect** code for this rule
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<!-- Arrow function returning .$el -->
|
|
20
|
+
<gl-popover :target="() => $refs.myButton.$el" />
|
|
21
|
+
|
|
22
|
+
<!-- Arrow function with explicit this -->
|
|
23
|
+
<gl-tooltip :target="() => this.$refs.myButton.$el" />
|
|
24
|
+
|
|
25
|
+
<!-- Function expression -->
|
|
26
|
+
<gl-popover :target="function() { return $refs.myButton.$el; }" />
|
|
27
|
+
|
|
28
|
+
<!-- PascalCase component names -->
|
|
29
|
+
<GlPopover :target="() => $refs.myButton.$el" />
|
|
30
|
+
<GlTooltip :target="() => $refs.myButton.$el" />
|
|
31
|
+
|
|
32
|
+
<!-- v-bind: long-form syntax -->
|
|
33
|
+
<gl-popover v-bind:target="() => $refs.myButton.$el" />
|
|
34
|
+
|
|
35
|
+
<!-- Detection is not limited to `$refs`: any callback returning a
|
|
36
|
+
component instance's `.$el` is flagged -->
|
|
37
|
+
<gl-popover :target="() => this.myButton.$el" />
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Examples of **correct** code for this rule
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<!-- Plain ref (no function) — always fine -->
|
|
44
|
+
<gl-popover :target="$refs.myButton" />
|
|
45
|
+
|
|
46
|
+
<!-- Arrow function without .$el — already correct -->
|
|
47
|
+
<gl-popover :target="() => $refs.myButton" />
|
|
48
|
+
|
|
49
|
+
<!-- DOM query — no .$el needed -->
|
|
50
|
+
<gl-popover :target="() => document.querySelector('#my-button')" />
|
|
51
|
+
|
|
52
|
+
<!-- .:target on an unrelated component — not flagged -->
|
|
53
|
+
<my-component :target="() => $refs.foo.$el" />
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Options
|
|
57
|
+
|
|
58
|
+
Nothing
|
|
59
|
+
|
|
60
|
+
## Related rules
|
|
61
|
+
|
|
62
|
+
- [`vue-no-data-toggle`](./vue-no-data-toggle.md)
|
|
63
|
+
|
|
64
|
+
## When Not To Use It
|
|
65
|
+
|
|
66
|
+
If your project is still using a version of `@gitlab/ui` that has **not** yet received the
|
|
67
|
+
companion fix (design.gitlab.com!6006), enabling this rule as `error` may cause runtime
|
|
68
|
+
issues. In that case, land the rule as `warn` or keep it off until the updated `@gitlab/ui`
|
|
69
|
+
version is deployed.
|
package/docs/rules.md
CHANGED
|
@@ -16,6 +16,7 @@ Available rules:
|
|
|
16
16
|
- [vue-no-data-toggle](./rules/vue-no-data-toggle.md): Restrict the use of `data-toggle` bootstrap behaviors within Vue templates
|
|
17
17
|
- [vue-no-hardcoded-urls](./rules/vue-no-hardcoded-urls.md): Disallow hardcoded URLs in Vue templates
|
|
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
|
+
- [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>`
|
|
19
20
|
- [vue-no-undef-apollo-properties](./rules/vue-no-undef-apollo-properties.md): Require Apollo query properties to be initialized in component data.
|
|
20
21
|
- [vue-prefer-dollar-scopedslots](./rules/vue-prefer-dollar-scopedslots.md): Prefer $scopedSlots over $slots for Vue 2.x.
|
|
21
22
|
- [vue-require-i18n-attribute-strings](./rules/vue-require-i18n-attribute-strings.md): Detect non externalized strings in vue `<template>` attributes
|
package/docs/usage.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
## Installation
|
|
2
2
|
|
|
3
|
-
You'll first need to install [ESLint](http://eslint.org)
|
|
3
|
+
You'll first need to install [ESLint](http://eslint.org) 9. The peer dependency is `^9.0.0`:
|
|
4
|
+
ESLint 8 and below are not supported, and ESLint 10 is not supported either.
|
|
4
5
|
|
|
5
6
|
```bash
|
|
6
|
-
yarn add --dev eslint
|
|
7
|
+
yarn add --dev eslint@^9.0.0
|
|
7
8
|
```
|
|
8
9
|
|
|
9
10
|
Next, install `@gitlab/eslint-plugin`:
|
|
@@ -16,80 +17,190 @@ yarn add --dev @gitlab/eslint-plugin
|
|
|
16
17
|
|
|
17
18
|
## Usage (configs)
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
All configs are [flat configs](https://eslint.org/docs/latest/use/configure/configuration-files),
|
|
21
|
+
so they belong in an `eslint.config.js` (or `.mjs`/`.cjs`) file. Each one is an **array** of flat
|
|
22
|
+
config objects, which you spread into your own array:
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
```js
|
|
25
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
extends:
|
|
26
|
-
- 'plugin:@gitlab/default'
|
|
27
|
+
module.exports = [...gitlab.configs.default];
|
|
27
28
|
```
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
ESM works the same way:
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
```js
|
|
33
|
+
import gitlab from '@gitlab/eslint-plugin';
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
parserOptions:
|
|
36
|
-
ecmaVersion: 2020
|
|
35
|
+
export default [...gitlab.configs.default];
|
|
37
36
|
```
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
If you need newer globals, you can define newer env as [described here][globals]. For example:
|
|
38
|
+
### Available configs
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
| Config | Contents |
|
|
41
|
+
| ------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
|
42
|
+
| `default` | The GitLab JavaScript and Vue rules together. What most projects want. |
|
|
43
|
+
| `base` | GitLab JavaScript style guide rules only, with no Vue rules. |
|
|
44
|
+
| `vue` | GitLab Vue style guide rules on top of `eslint-plugin-vue`'s recommended set. Vue rules only — combine it with `base`. |
|
|
45
|
+
| `typescript` | `base` plus the TypeScript layer. Requires extra dependencies, see [TypeScript](#typescript). |
|
|
46
|
+
| `jest` | Jest rules, on top of `eslint-plugin-jest`'s recommended set. Requires `jest` in your project. |
|
|
47
|
+
| `i18n` | i18n linting for the GitLab project. |
|
|
48
|
+
| `tailwind` | Tailwind utility-class rules. |
|
|
49
|
+
|
|
50
|
+
`default` is not simply `base` followed by `vue`: the two configs place
|
|
51
|
+
[`eslint-config-prettier`](https://github.com/prettier/eslint-config-prettier) differently relative
|
|
52
|
+
to the Vue preset, which is deliberate and matches what these configs have always resolved to. Use
|
|
53
|
+
`default` if you want both; use `base` and `vue` separately only if you need to interleave something
|
|
54
|
+
between them.
|
|
55
|
+
|
|
56
|
+
### Composing configs
|
|
57
|
+
|
|
58
|
+
Because every config is an array, you can spread several of them:
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
62
|
+
|
|
63
|
+
module.exports = [...gitlab.configs.default, ...gitlab.configs.i18n];
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The configs are not restricted to particular files, so they apply to everything ESLint lints. To
|
|
67
|
+
scope one to a subset of your project, add a `files` pattern to each of its entries:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
71
|
+
|
|
72
|
+
module.exports = [
|
|
73
|
+
...gitlab.configs.default,
|
|
74
|
+
...gitlab.configs.jest.map((config) => ({ ...config, files: ['**/*.spec.js'] })),
|
|
75
|
+
];
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Do not do this to `vue`, `default` or `typescript`.** Those three already set `files` on some of
|
|
79
|
+
their entries, and `{ ...config, files: [...] }` overwrites that key rather than narrowing it. On
|
|
80
|
+
`vue` and `default` you would drop the scope from the two `**/*.vue` entries, so Vue
|
|
81
|
+
single-file-component rules would start applying to plain `.js` files. On `typescript` you would
|
|
82
|
+
drop the scope from its `**/*.ts` and `**/*.test.ts` entries, so the TypeScript parser and the
|
|
83
|
+
type-aware rules would be applied to every file the pattern matches — including `.spec.js`, which
|
|
84
|
+
they cannot parse. Scope those configs by narrowing the patterns they
|
|
85
|
+
already declare, or by adding your own config object after them, not by replacing `files` wholesale.
|
|
86
|
+
`jest`, `i18n`, `tailwind` and `base` declare no `files` key and are safe to map this way.
|
|
87
|
+
|
|
88
|
+
### Parsers and language options
|
|
89
|
+
|
|
90
|
+
`base` and `default` use `espree`, shipped with `eslint`, at `ecmaVersion: 'latest'`, so even the
|
|
91
|
+
newest JavaScript syntax parses. `vue` (and therefore `default`) uses
|
|
92
|
+
[`vue-eslint-parser`](https://github.com/vuejs/vue-eslint-parser) with `espree` for `<script>`
|
|
93
|
+
blocks.
|
|
94
|
+
|
|
95
|
+
To change a language option, add a config object of your own after the GitLab configs — later
|
|
96
|
+
entries win:
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
100
|
+
|
|
101
|
+
module.exports = [
|
|
102
|
+
...gitlab.configs.default,
|
|
103
|
+
{
|
|
104
|
+
languageOptions: {
|
|
105
|
+
ecmaVersion: 2020,
|
|
106
|
+
globals: {
|
|
107
|
+
gon: 'readonly',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
];
|
|
45
112
|
```
|
|
46
113
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
and the [`vue-eslint-parser` docs][vue-eslint-parser-config] if you lint VUE files as well.
|
|
114
|
+
See the ESLint docs on [language options][language-options] and
|
|
115
|
+
[configuring a parser][eslint-parser-config] for the full set of keys.
|
|
50
116
|
|
|
51
|
-
[
|
|
52
|
-
[globals]: https://eslint.org/docs/latest/use/configure/language-options#specifying-environments
|
|
117
|
+
[language-options]: https://eslint.org/docs/latest/use/configure/language-options
|
|
53
118
|
[eslint-parser-config]: https://eslint.org/docs/latest/use/configure/parser
|
|
54
|
-
[vue-eslint-parser-config]: https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
|
|
55
119
|
|
|
56
|
-
###
|
|
120
|
+
### TypeScript
|
|
57
121
|
|
|
58
|
-
|
|
59
|
-
|
|
122
|
+
The `typescript` config needs `@typescript-eslint/parser`, `@typescript-eslint/eslint-plugin` and
|
|
123
|
+
`typescript` in your own project. They are optional peer dependencies of this package, so your
|
|
124
|
+
project controls their versions:
|
|
60
125
|
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
- 'plugin:@gitlab/i18n'
|
|
126
|
+
```bash
|
|
127
|
+
yarn add --dev typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
|
64
128
|
```
|
|
65
129
|
|
|
66
|
-
|
|
130
|
+
```js
|
|
131
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
67
132
|
|
|
68
|
-
|
|
69
|
-
|
|
133
|
+
module.exports = [...gitlab.configs.typescript];
|
|
134
|
+
```
|
|
70
135
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
136
|
+
The `**/*.ts` layer is type-aware: it sets `parserOptions.project` to `./tsconfig.json`, so a
|
|
137
|
+
`tsconfig.json` must exist at the directory ESLint runs from and must include the files you lint.
|
|
138
|
+
If your `tsconfig.json` lives elsewhere, override it after spreading the config:
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
142
|
+
|
|
143
|
+
module.exports = [
|
|
144
|
+
...gitlab.configs.typescript,
|
|
145
|
+
{
|
|
146
|
+
files: ['**/*.ts'],
|
|
147
|
+
languageOptions: {
|
|
148
|
+
parserOptions: { project: ['./config/tsconfig.eslint.json'] },
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
];
|
|
74
152
|
```
|
|
75
153
|
|
|
154
|
+
Requiring `@gitlab/eslint-plugin` does **not** load the TypeScript packages unless you actually read
|
|
155
|
+
`configs.typescript`; each config is exposed through a getter. One consequence: spreading the whole
|
|
156
|
+
`configs` object (`{ ...gitlab.configs }`), deep-cloning it or passing it to `JSON.stringify` reads
|
|
157
|
+
every config at once and throws if the TypeScript packages are not installed. Read the configs you
|
|
158
|
+
need by name instead.
|
|
159
|
+
|
|
76
160
|
## Usage (rules)
|
|
77
161
|
|
|
78
|
-
|
|
162
|
+
To use individual rules without one of the configs, register the plugin yourself and enable the
|
|
163
|
+
rules you want:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
const gitlab = require('@gitlab/eslint-plugin');
|
|
79
167
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
168
|
+
module.exports = [
|
|
169
|
+
{
|
|
170
|
+
plugins: { '@gitlab': gitlab },
|
|
171
|
+
rules: {
|
|
172
|
+
'@gitlab/require-i18n-strings': 'error',
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
];
|
|
83
176
|
```
|
|
84
177
|
|
|
85
|
-
|
|
178
|
+
See [Available rules](./rules.md) for the full list.
|
|
86
179
|
|
|
87
|
-
|
|
180
|
+
## Migrating from the eslintrc configs
|
|
88
181
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
182
|
+
Up to and including v21, this package shipped eslintrc configs used through `extends`. Those are
|
|
183
|
+
gone. The replacement is a spread of the same-named config:
|
|
184
|
+
|
|
185
|
+
| Before (`.eslintrc.yml`) | After (`eslint.config.js`) |
|
|
186
|
+
| ---------------------------------------- | ------------------------------ |
|
|
187
|
+
| `extends: ['plugin:@gitlab/default']` | `...gitlab.configs.default` |
|
|
188
|
+
| `extends: ['plugin:@gitlab/base']` | `...gitlab.configs.base` |
|
|
189
|
+
| `extends: ['plugin:@gitlab/vue']` | `...gitlab.configs.vue` |
|
|
190
|
+
| `extends: ['plugin:@gitlab/typescript']` | `...gitlab.configs.typescript` |
|
|
191
|
+
| `extends: ['plugin:@gitlab/jest']` | `...gitlab.configs.jest` |
|
|
192
|
+
| `extends: ['plugin:@gitlab/i18n']` | `...gitlab.configs.i18n` |
|
|
193
|
+
| `extends: ['plugin:@gitlab/tailwind']` | `...gitlab.configs.tailwind` |
|
|
194
|
+
|
|
195
|
+
The eight fragments that `base` is assembled from — `plugin:@gitlab/best-practices`,
|
|
196
|
+
`plugin:@gitlab/errors`, `plugin:@gitlab/es6`, `plugin:@gitlab/imports`, `plugin:@gitlab/node`,
|
|
197
|
+
`plugin:@gitlab/strict`, `plugin:@gitlab/style` and `plugin:@gitlab/variables` — were also exported
|
|
198
|
+
as configs. They are no longer part of the public surface; extend `base` instead.
|
|
199
|
+
|
|
200
|
+
ESLint's own [configuration migration guide][eslint-migration] covers the rest of the move, and
|
|
201
|
+
`npx @eslint/migrate-config .eslintrc` can convert the parts of your config that are not GitLab's.
|
|
202
|
+
|
|
203
|
+
[eslint-migration]: https://eslint.org/docs/latest/use/configure/migration-guide
|
|
93
204
|
|
|
94
205
|
## VueJS (.vue files)
|
|
95
206
|
|
package/eslint9/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* @deprecated Use the package root instead:
|
|
3
|
+
* const gitlab = require('@gitlab/eslint-plugin');
|
|
4
|
+
*
|
|
5
|
+
* Kept so existing `@gitlab/eslint-plugin/eslint9` imports keep resolving.
|
|
6
|
+
* Scheduled for removal in the ESLint 10 major.
|
|
3
7
|
*/
|
|
4
|
-
module.exports =
|
|
5
|
-
configs: {
|
|
6
|
-
base: require('./configs/base.js'),
|
|
7
|
-
typescript: require('./configs/typescript.js'),
|
|
8
|
-
},
|
|
9
|
-
};
|
|
8
|
+
module.exports = require('../lib/index.js');
|
package/lib/configs/base/es6.js
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
env: {
|
|
3
|
-
es6: true,
|
|
4
|
-
},
|
|
5
|
-
parserOptions: {
|
|
6
|
-
ecmaVersion: 6,
|
|
7
|
-
sourceType: 'module',
|
|
8
|
-
ecmaFeatures: {
|
|
9
|
-
generators: false,
|
|
10
|
-
objectLiteralDuplicateProperties: false,
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
|
|
14
2
|
rules: {
|
|
15
3
|
// enforces no braces where they can be omitted
|
|
16
4
|
// https://eslint.org/docs/rules/arrow-body-style
|