@fast-china/eslint-config 2.1.7 → 2.1.8
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/CONTRIBUTING.md +2 -2
- package/README.md +66 -142
- package/README.zh.md +64 -142
- package/dist/configs/environment.mjs +2 -0
- package/dist/configs/environment.mjs.map +1 -1
- package/dist/configs/ignores.mjs +0 -1
- package/dist/configs/ignores.mjs.map +1 -1
- package/dist/configs/import.mjs +4 -1
- package/dist/configs/import.mjs.map +1 -1
- package/dist/configs/index.d.mts +2 -2
- package/dist/configs/index.mjs +2 -2
- package/dist/configs/javascript.mjs +3 -1
- package/dist/configs/javascript.mjs.map +1 -1
- package/dist/configs/json.mjs +3 -1
- package/dist/configs/json.mjs.map +1 -1
- package/dist/configs/markdown.d.mts +2 -1
- package/dist/configs/markdown.mjs +4 -2
- package/dist/configs/markdown.mjs.map +1 -1
- package/dist/configs/prettier.mjs +1 -1
- package/dist/configs/prettier.mjs.map +1 -1
- package/dist/configs/sort-package.d.mts +1 -1
- package/dist/configs/sort-package.mjs +1 -1
- package/dist/configs/sort-package.mjs.map +1 -1
- package/dist/configs/sort-tsconfig.d.mts +2 -2
- package/dist/configs/sort-tsconfig.mjs +2 -2
- package/dist/configs/sort-tsconfig.mjs.map +1 -1
- package/dist/configs/typescript.d.mts +11 -7
- package/dist/configs/typescript.mjs +25 -22
- package/dist/configs/typescript.mjs.map +1 -1
- package/dist/configs/uniapp.mjs +19 -13
- package/dist/configs/uniapp.mjs.map +1 -1
- package/dist/configs/vue.d.mts +18 -3
- package/dist/configs/vue.mjs +59 -9
- package/dist/configs/vue.mjs.map +1 -1
- package/dist/constants/index.d.mts +4 -0
- package/dist/constants/index.mjs +5 -1
- package/dist/constants/index.mjs.map +1 -1
- package/dist/index.d.mts +37 -58
- package/dist/index.mjs +43 -47
- package/dist/index.mjs.map +1 -1
- package/dist/rules/angular.d.mts +28 -0
- package/dist/rules/angular.mjs +28 -0
- package/dist/rules/angular.mjs.map +1 -1
- package/dist/rules/common.d.mts +16 -6
- package/dist/rules/common.mjs +16 -13
- package/dist/rules/common.mjs.map +1 -1
- package/dist/rules/import.d.mts +9 -0
- package/dist/rules/import.mjs +24 -0
- package/dist/rules/import.mjs.map +1 -1
- package/dist/rules/index.d.mts +2 -2
- package/dist/rules/index.mjs +2 -2
- package/dist/rules/javascript.d.mts +18 -0
- package/dist/rules/javascript.mjs +18 -0
- package/dist/rules/javascript.mjs.map +1 -1
- package/dist/rules/lodash.d.mts +2 -0
- package/dist/rules/lodash.mjs +6 -2
- package/dist/rules/lodash.mjs.map +1 -1
- package/dist/rules/react.d.mts +13 -0
- package/dist/rules/react.mjs +13 -0
- package/dist/rules/react.mjs.map +1 -1
- package/dist/rules/regexp.d.mts +25 -0
- package/dist/rules/regexp.mjs +25 -0
- package/dist/rules/regexp.mjs.map +1 -1
- package/dist/rules/sort-package.d.mts +3 -1
- package/dist/rules/sort-package.mjs +3 -1
- package/dist/rules/sort-package.mjs.map +1 -1
- package/dist/rules/sort-tsconfig.d.mts +3 -1
- package/dist/rules/sort-tsconfig.mjs +3 -1
- package/dist/rules/sort-tsconfig.mjs.map +1 -1
- package/dist/rules/typescript.d.mts +81 -13
- package/dist/rules/typescript.mjs +83 -15
- package/dist/rules/typescript.mjs.map +1 -1
- package/dist/rules/vue.d.mts +65 -10
- package/dist/rules/vue.mjs +41 -14
- package/dist/rules/vue.mjs.map +1 -1
- package/docs/engineering-audit.zh.md +45 -49
- package/docs/rules/angular.zh.md +721 -0
- package/docs/rules/core.zh.md +3031 -0
- package/docs/rules/index.zh.md +38 -0
- package/docs/rules/json.zh.md +784 -0
- package/docs/rules/markdown.zh.md +449 -0
- package/docs/rules/react.zh.md +2091 -0
- package/docs/rules/typescript.zh.md +2051 -0
- package/docs/rules/vue.zh.md +3016 -0
- package/docs/rules-risk.md +85 -91
- package/docs/rules-risk.zh.md +76 -82
- package/package.json +4 -2
|
@@ -0,0 +1,721 @@
|
|
|
1
|
+
<!-- 此文件由 scripts/rules-docs.ts 生成,请勿手工编辑。 -->
|
|
2
|
+
|
|
3
|
+
# Angular 与 Angular 模板
|
|
4
|
+
|
|
5
|
+
本页记录当前依赖版本和仓库配置最终产生的 28 条规则。每条规则均列出实际严重级别、生效范围、上游说明、常见报告以及错误/正确示例。
|
|
6
|
+
|
|
7
|
+
## 仓库显式规则(28 条)
|
|
8
|
+
|
|
9
|
+
### `@angular-eslint/contextual-lifecycle`
|
|
10
|
+
|
|
11
|
+
生命周期方法只能出现在对应的 Angular 组件或指令上下文中,避免无效钩子。
|
|
12
|
+
|
|
13
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
14
|
+
- 自动修复:不支持或上游未声明
|
|
15
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/contextual-lifecycle.md)
|
|
16
|
+
- 常见报告:`Angular will not invoke the '{{methodName}}' lifecycle method within '@{{classDecoratorName}}()' classes`
|
|
17
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
18
|
+
|
|
19
|
+
错误示例:
|
|
20
|
+
|
|
21
|
+
<!-- prettier-ignore -->
|
|
22
|
+
````ts
|
|
23
|
+
import { Injectable } from "@angular/core";
|
|
24
|
+
@Injectable()
|
|
25
|
+
class UserService { ngOnInit(): void { console.log("initialized"); } }
|
|
26
|
+
````
|
|
27
|
+
|
|
28
|
+
正确示例:
|
|
29
|
+
|
|
30
|
+
<!-- prettier-ignore -->
|
|
31
|
+
````ts
|
|
32
|
+
import { Component, OnInit } from "@angular/core";
|
|
33
|
+
@Component({ selector: "app-page", template: `` })
|
|
34
|
+
class PageComponent implements OnInit { ngOnInit(): void { console.log("initialized"); } }
|
|
35
|
+
````
|
|
36
|
+
|
|
37
|
+
### `@angular-eslint/no-empty-lifecycle-method`
|
|
38
|
+
|
|
39
|
+
空生命周期方法没有行为且容易误导维护者,应直接移除。
|
|
40
|
+
|
|
41
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
42
|
+
- 自动修复:不支持或上游未声明
|
|
43
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/no-empty-lifecycle-method.md)
|
|
44
|
+
- 常见报告:`Lifecycle methods should not be empty`;`Remove lifecycle method`
|
|
45
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
46
|
+
|
|
47
|
+
错误示例:
|
|
48
|
+
|
|
49
|
+
<!-- prettier-ignore -->
|
|
50
|
+
````ts
|
|
51
|
+
import { Component, OnInit } from "@angular/core";
|
|
52
|
+
@Component({ selector: "app-page", template: `` })
|
|
53
|
+
class PageComponent implements OnInit { ngOnInit(): void {} }
|
|
54
|
+
````
|
|
55
|
+
|
|
56
|
+
正确示例:
|
|
57
|
+
|
|
58
|
+
<!-- prettier-ignore -->
|
|
59
|
+
````ts
|
|
60
|
+
import { Component, OnInit } from "@angular/core";
|
|
61
|
+
@Component({ selector: "app-page", template: `` })
|
|
62
|
+
class PageComponent implements OnInit { ngOnInit(): void { console.log("initialized"); } }
|
|
63
|
+
````
|
|
64
|
+
|
|
65
|
+
### `@angular-eslint/no-input-rename`
|
|
66
|
+
|
|
67
|
+
Input 别名会让模板 API 与类属性名称分离,增加搜索和重构成本。
|
|
68
|
+
|
|
69
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
70
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
71
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/no-input-rename.md)
|
|
72
|
+
- 常见报告:`Input bindings should not be aliased (https://angular.dev/guide/components/inputs#choosing-input-names)`;`Remove alias name`;`Remove alias name and use it as the original name`
|
|
73
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
74
|
+
|
|
75
|
+
错误示例:
|
|
76
|
+
|
|
77
|
+
<!-- prettier-ignore -->
|
|
78
|
+
````ts
|
|
79
|
+
import { Component, Input } from "@angular/core";
|
|
80
|
+
@Component({ selector: "app-user", template: `` })
|
|
81
|
+
class UserComponent { @Input("userName") name = ""; }
|
|
82
|
+
````
|
|
83
|
+
|
|
84
|
+
正确示例:
|
|
85
|
+
|
|
86
|
+
<!-- prettier-ignore -->
|
|
87
|
+
````ts
|
|
88
|
+
import { Component, Input } from "@angular/core";
|
|
89
|
+
@Component({ selector: "app-user", template: `` })
|
|
90
|
+
class UserComponent { @Input() userName = ""; }
|
|
91
|
+
````
|
|
92
|
+
|
|
93
|
+
### `@angular-eslint/no-inputs-metadata-property`
|
|
94
|
+
|
|
95
|
+
统一使用 `input()` 或 `@Input` 声明输入,避免与 metadata 数组混用两套 API。
|
|
96
|
+
|
|
97
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
98
|
+
- 自动修复:不支持或上游未声明
|
|
99
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/no-inputs-metadata-property.md)
|
|
100
|
+
- 常见报告:`Use '@Input' rather than the 'inputs' metadata property`
|
|
101
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
102
|
+
|
|
103
|
+
错误示例:
|
|
104
|
+
|
|
105
|
+
<!-- prettier-ignore -->
|
|
106
|
+
````ts
|
|
107
|
+
@Component({ selector: "app-user", inputs: ["name"], template: `` })
|
|
108
|
+
class UserComponent { name = ""; }
|
|
109
|
+
````
|
|
110
|
+
|
|
111
|
+
正确示例:
|
|
112
|
+
|
|
113
|
+
<!-- prettier-ignore -->
|
|
114
|
+
````ts
|
|
115
|
+
@Component({ selector: "app-user", template: `` })
|
|
116
|
+
class UserComponent { @Input() name = ""; }
|
|
117
|
+
````
|
|
118
|
+
|
|
119
|
+
### `@angular-eslint/no-output-native`
|
|
120
|
+
|
|
121
|
+
输出名称不得覆盖原生 DOM 事件,否则模板事件含义容易混淆。
|
|
122
|
+
|
|
123
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
124
|
+
- 自动修复:不支持或上游未声明
|
|
125
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/no-output-native.md)
|
|
126
|
+
- 常见报告:`Output bindings, including aliases, should not be named as standard DOM events`
|
|
127
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
128
|
+
|
|
129
|
+
错误示例:
|
|
130
|
+
|
|
131
|
+
<!-- prettier-ignore -->
|
|
132
|
+
````ts
|
|
133
|
+
import { Component, EventEmitter, Output } from "@angular/core";
|
|
134
|
+
@Component({ selector: "app-editor", template: `` })
|
|
135
|
+
class EditorComponent { @Output() click = new EventEmitter<void>(); }
|
|
136
|
+
````
|
|
137
|
+
|
|
138
|
+
正确示例:
|
|
139
|
+
|
|
140
|
+
<!-- prettier-ignore -->
|
|
141
|
+
````ts
|
|
142
|
+
import { Component, EventEmitter, Output } from "@angular/core";
|
|
143
|
+
@Component({ selector: "app-editor", template: `` })
|
|
144
|
+
class EditorComponent { @Output() saved = new EventEmitter<void>(); }
|
|
145
|
+
````
|
|
146
|
+
|
|
147
|
+
### `@angular-eslint/no-output-on-prefix`
|
|
148
|
+
|
|
149
|
+
输出本身已经表达事件语义,不使用 `on` 前缀以保持 Angular 公共 API 约定。
|
|
150
|
+
|
|
151
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
152
|
+
- 自动修复:不支持或上游未声明
|
|
153
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/no-output-on-prefix.md)
|
|
154
|
+
- 常见报告:`Output bindings, including aliases, should not be named "on", nor prefixed with it (https://angular.dev/guide/components/outputs#choosing-event-names)`
|
|
155
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
156
|
+
|
|
157
|
+
错误示例:
|
|
158
|
+
|
|
159
|
+
<!-- prettier-ignore -->
|
|
160
|
+
````ts
|
|
161
|
+
import { Component, EventEmitter, Output } from "@angular/core";
|
|
162
|
+
@Component({ selector: "app-editor", template: `` })
|
|
163
|
+
class EditorComponent { @Output() onSaved = new EventEmitter<void>(); }
|
|
164
|
+
````
|
|
165
|
+
|
|
166
|
+
正确示例:
|
|
167
|
+
|
|
168
|
+
<!-- prettier-ignore -->
|
|
169
|
+
````ts
|
|
170
|
+
import { Component, EventEmitter, Output } from "@angular/core";
|
|
171
|
+
@Component({ selector: "app-editor", template: `` })
|
|
172
|
+
class EditorComponent { @Output() saved = new EventEmitter<void>(); }
|
|
173
|
+
````
|
|
174
|
+
|
|
175
|
+
### `@angular-eslint/no-output-rename`
|
|
176
|
+
|
|
177
|
+
Output 别名会让模板 API 与类属性名称分离,增加搜索和重构成本。
|
|
178
|
+
|
|
179
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
180
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
181
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/no-output-rename.md)
|
|
182
|
+
- 常见报告:`Output bindings should not be aliased (https://angular.dev/guide/components/outputs#choosing-event-names)`;`Remove alias name`;`Remove alias name and use it as the original name`
|
|
183
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
184
|
+
|
|
185
|
+
错误示例:
|
|
186
|
+
|
|
187
|
+
<!-- prettier-ignore -->
|
|
188
|
+
````ts
|
|
189
|
+
import { Component, EventEmitter, Output } from "@angular/core";
|
|
190
|
+
@Component({ selector: "app-editor", template: `` })
|
|
191
|
+
class EditorComponent { @Output("saved") save = new EventEmitter<void>(); }
|
|
192
|
+
````
|
|
193
|
+
|
|
194
|
+
正确示例:
|
|
195
|
+
|
|
196
|
+
<!-- prettier-ignore -->
|
|
197
|
+
````ts
|
|
198
|
+
import { Component, EventEmitter, Output } from "@angular/core";
|
|
199
|
+
@Component({ selector: "app-editor", template: `` })
|
|
200
|
+
class EditorComponent { @Output() saved = new EventEmitter<void>(); }
|
|
201
|
+
````
|
|
202
|
+
|
|
203
|
+
### `@angular-eslint/no-outputs-metadata-property`
|
|
204
|
+
|
|
205
|
+
统一使用 `output()` 或 `@Output` 声明输出,避免与 metadata 数组混用两套 API。
|
|
206
|
+
|
|
207
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
208
|
+
- 自动修复:不支持或上游未声明
|
|
209
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/no-outputs-metadata-property.md)
|
|
210
|
+
- 常见报告:`Use '@Output' rather than the 'outputs' metadata property`
|
|
211
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
212
|
+
|
|
213
|
+
错误示例:
|
|
214
|
+
|
|
215
|
+
<!-- prettier-ignore -->
|
|
216
|
+
````ts
|
|
217
|
+
@Component({ selector: "app-editor", outputs: ["saved"], template: `` })
|
|
218
|
+
class EditorComponent { saved = new EventEmitter<void>(); }
|
|
219
|
+
````
|
|
220
|
+
|
|
221
|
+
正确示例:
|
|
222
|
+
|
|
223
|
+
<!-- prettier-ignore -->
|
|
224
|
+
````ts
|
|
225
|
+
@Component({ selector: "app-editor", template: `` })
|
|
226
|
+
class EditorComponent { @Output() saved = new EventEmitter<void>(); }
|
|
227
|
+
````
|
|
228
|
+
|
|
229
|
+
### `@angular-eslint/prefer-inject`
|
|
230
|
+
|
|
231
|
+
Angular 推荐使用 `inject()` 统一依赖注入写法。
|
|
232
|
+
|
|
233
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
234
|
+
- 自动修复:不支持或上游未声明
|
|
235
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-inject.md)
|
|
236
|
+
- 常见报告:`Prefer using the inject() function over constructor parameter injection. Use Angular's migration schematic to automatically refactor: ng generate @angular/core:inject`
|
|
237
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
238
|
+
|
|
239
|
+
错误示例:
|
|
240
|
+
|
|
241
|
+
<!-- prettier-ignore -->
|
|
242
|
+
````ts
|
|
243
|
+
@Injectable()
|
|
244
|
+
class UserService { constructor(private readonly api: ApiService) {} }
|
|
245
|
+
````
|
|
246
|
+
|
|
247
|
+
正确示例:
|
|
248
|
+
|
|
249
|
+
<!-- prettier-ignore -->
|
|
250
|
+
````ts
|
|
251
|
+
@Injectable()
|
|
252
|
+
class UserService { private readonly api = inject(ApiService); }
|
|
253
|
+
````
|
|
254
|
+
|
|
255
|
+
### `@angular-eslint/prefer-on-push-component-change-detection`
|
|
256
|
+
|
|
257
|
+
Angular 22 默认采用 `OnPush`,禁止组件显式退回 `Eager` 或旧的 `Default` 策略。
|
|
258
|
+
|
|
259
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
260
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
261
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-on-push-component-change-detection.md)
|
|
262
|
+
- 常见报告:`Components should not opt out of the default 'ChangeDetectionStrategy.OnPush' change detection strategy`;`Remove 'changeDetection' to use the default ('ChangeDetectionStrategy.OnPush')`;`'changeDetection: ChangeDetectionStrategy.OnPush' is redundant because 'ChangeDetectionStrategy.OnPush' is the default change detection strategy`
|
|
263
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
264
|
+
|
|
265
|
+
错误示例:
|
|
266
|
+
|
|
267
|
+
<!-- prettier-ignore -->
|
|
268
|
+
````ts
|
|
269
|
+
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
|
270
|
+
@Component({ selector: "app-user", template: ``, changeDetection: ChangeDetectionStrategy.Eager })
|
|
271
|
+
class UserComponent {}
|
|
272
|
+
````
|
|
273
|
+
|
|
274
|
+
正确示例:
|
|
275
|
+
|
|
276
|
+
<!-- prettier-ignore -->
|
|
277
|
+
````ts
|
|
278
|
+
import { Component } from "@angular/core";
|
|
279
|
+
@Component({ selector: "app-user", template: `` })
|
|
280
|
+
class UserComponent {}
|
|
281
|
+
````
|
|
282
|
+
|
|
283
|
+
### `@angular-eslint/prefer-standalone`
|
|
284
|
+
|
|
285
|
+
独立组件是现代 Angular 的默认模型。
|
|
286
|
+
|
|
287
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
288
|
+
- 自动修复:不支持或上游未声明
|
|
289
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-standalone.md)
|
|
290
|
+
- 常见报告:`Components, Directives and Pipes should not opt out of standalone. Following this guide is highly recommended: https://angular.dev/reference/migrations/standalone`;`Quickly remove 'standalone: false'. NOTE - Following this guide is highly recommended: https://angular.dev/reference/migrations/standalone`
|
|
291
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
292
|
+
|
|
293
|
+
错误示例:
|
|
294
|
+
|
|
295
|
+
<!-- prettier-ignore -->
|
|
296
|
+
````ts
|
|
297
|
+
@Component({ selector: "app-user", standalone: false, template: `` })
|
|
298
|
+
class UserComponent {}
|
|
299
|
+
````
|
|
300
|
+
|
|
301
|
+
正确示例:
|
|
302
|
+
|
|
303
|
+
<!-- prettier-ignore -->
|
|
304
|
+
````ts
|
|
305
|
+
@Component({ selector: "app-user", standalone: true, template: `` })
|
|
306
|
+
class UserComponent {}
|
|
307
|
+
````
|
|
308
|
+
|
|
309
|
+
### `@angular-eslint/template/alt-text`
|
|
310
|
+
|
|
311
|
+
图片和图像型元素需要替代文本,确保非视觉用户能获得等价信息。
|
|
312
|
+
|
|
313
|
+
- 生效级别与范围:error: Angular HTML
|
|
314
|
+
- 自动修复:不支持或上游未声明
|
|
315
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/alt-text.md)
|
|
316
|
+
- 常见报告:`<{{element}}/> element must have a text alternative.`
|
|
317
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
318
|
+
|
|
319
|
+
错误示例:
|
|
320
|
+
|
|
321
|
+
<!-- prettier-ignore -->
|
|
322
|
+
````html
|
|
323
|
+
<img src="user.png">
|
|
324
|
+
````
|
|
325
|
+
|
|
326
|
+
正确示例:
|
|
327
|
+
|
|
328
|
+
<!-- prettier-ignore -->
|
|
329
|
+
````html
|
|
330
|
+
<img src="user.png" alt="User avatar">
|
|
331
|
+
````
|
|
332
|
+
|
|
333
|
+
### `@angular-eslint/template/banana-in-box`
|
|
334
|
+
|
|
335
|
+
双向绑定必须使用 `[(...)]` 顺序,反写的“香蕉盒”通常是模板笔误。
|
|
336
|
+
|
|
337
|
+
- 生效级别与范围:error: Angular HTML
|
|
338
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
339
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/banana-in-box.md)
|
|
340
|
+
- 常见报告:`Invalid binding syntax. Use [(expr)] instead`
|
|
341
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
342
|
+
|
|
343
|
+
错误示例:
|
|
344
|
+
|
|
345
|
+
<!-- prettier-ignore -->
|
|
346
|
+
````html
|
|
347
|
+
<input ([ngModel])="name">
|
|
348
|
+
````
|
|
349
|
+
|
|
350
|
+
正确示例:
|
|
351
|
+
|
|
352
|
+
<!-- prettier-ignore -->
|
|
353
|
+
````html
|
|
354
|
+
<input [(ngModel)]="name">
|
|
355
|
+
````
|
|
356
|
+
|
|
357
|
+
### `@angular-eslint/template/click-events-have-key-events`
|
|
358
|
+
|
|
359
|
+
`click` 交互需要键盘等价入口,避免仅鼠标用户可操作。
|
|
360
|
+
|
|
361
|
+
- 生效级别与范围:error: Angular HTML
|
|
362
|
+
- 自动修复:不支持或上游未声明
|
|
363
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/click-events-have-key-events.md)
|
|
364
|
+
- 常见报告:`click must be accompanied by either keyup, keydown or keypress event for accessibility.`;`click must be accompanied by a keyup, keydown or keypress event that specifies a key (e.g. '(keydown.enter)') for accessibility.`;`click must be accompanied by a keyup, keydown or keypress event for one of the allowed keys ({{allowedKeyCodes}}) for accessibility.`
|
|
365
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
366
|
+
|
|
367
|
+
错误示例:
|
|
368
|
+
|
|
369
|
+
<!-- prettier-ignore -->
|
|
370
|
+
````html
|
|
371
|
+
<div (click)="open()">Open</div>
|
|
372
|
+
````
|
|
373
|
+
|
|
374
|
+
正确示例:
|
|
375
|
+
|
|
376
|
+
<!-- prettier-ignore -->
|
|
377
|
+
````html
|
|
378
|
+
<button type="button" (click)="open()">Open</button>
|
|
379
|
+
````
|
|
380
|
+
|
|
381
|
+
### `@angular-eslint/template/elements-content`
|
|
382
|
+
|
|
383
|
+
需要可访问名称的元素不得为空,避免读屏软件播报无意义控件。
|
|
384
|
+
|
|
385
|
+
- 生效级别与范围:error: Angular HTML
|
|
386
|
+
- 自动修复:不支持或上游未声明
|
|
387
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/elements-content.md)
|
|
388
|
+
- 常见报告:`<{{element}}> should have content`
|
|
389
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
390
|
+
|
|
391
|
+
错误示例:
|
|
392
|
+
|
|
393
|
+
<!-- prettier-ignore -->
|
|
394
|
+
````html
|
|
395
|
+
<button></button>
|
|
396
|
+
````
|
|
397
|
+
|
|
398
|
+
正确示例:
|
|
399
|
+
|
|
400
|
+
<!-- prettier-ignore -->
|
|
401
|
+
````html
|
|
402
|
+
<button>Save</button>
|
|
403
|
+
````
|
|
404
|
+
|
|
405
|
+
### `@angular-eslint/template/eqeqeq`
|
|
406
|
+
|
|
407
|
+
模板比较使用严格等号,避免 Angular 表达式中的隐式类型转换。
|
|
408
|
+
|
|
409
|
+
- 生效级别与范围:error: Angular HTML
|
|
410
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
411
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/eqeqeq.md)
|
|
412
|
+
- 常见报告:`Expected '{{expectedOperation}}' but received '{{actualOperation}}'`;`Replace '{{actualOperation}}' with '{{expectedOperation}}'`
|
|
413
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
414
|
+
|
|
415
|
+
错误示例:
|
|
416
|
+
|
|
417
|
+
<!-- prettier-ignore -->
|
|
418
|
+
````html
|
|
419
|
+
<p *ngIf="count == 0">Empty</p>
|
|
420
|
+
````
|
|
421
|
+
|
|
422
|
+
正确示例:
|
|
423
|
+
|
|
424
|
+
<!-- prettier-ignore -->
|
|
425
|
+
````html
|
|
426
|
+
<p *ngIf="count === 0">Empty</p>
|
|
427
|
+
````
|
|
428
|
+
|
|
429
|
+
### `@angular-eslint/template/interactive-supports-focus`
|
|
430
|
+
|
|
431
|
+
具有交互语义的元素必须可聚焦,确保键盘导航能够到达。
|
|
432
|
+
|
|
433
|
+
- 生效级别与范围:error: Angular HTML
|
|
434
|
+
- 自动修复:不支持或上游未声明
|
|
435
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/interactive-supports-focus.md)
|
|
436
|
+
- 常见报告:`Elements with interaction handlers must be focusable.`
|
|
437
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
438
|
+
|
|
439
|
+
错误示例:
|
|
440
|
+
|
|
441
|
+
<!-- prettier-ignore -->
|
|
442
|
+
````html
|
|
443
|
+
<div role="button" (click)="save()">Save</div>
|
|
444
|
+
````
|
|
445
|
+
|
|
446
|
+
正确示例:
|
|
447
|
+
|
|
448
|
+
<!-- prettier-ignore -->
|
|
449
|
+
````html
|
|
450
|
+
<div role="button" tabindex="0" (click)="save()" (keydown.enter)="save()">Save</div>
|
|
451
|
+
````
|
|
452
|
+
|
|
453
|
+
### `@angular-eslint/template/label-has-associated-control`
|
|
454
|
+
|
|
455
|
+
表单 `label` 必须关联控件,扩大可点击区域并为辅助技术提供名称。
|
|
456
|
+
|
|
457
|
+
- 生效级别与范围:error: Angular HTML
|
|
458
|
+
- 自动修复:不支持或上游未声明
|
|
459
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/label-has-associated-control.md)
|
|
460
|
+
- 常见报告:`A label component must be associated with a form element`
|
|
461
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
462
|
+
|
|
463
|
+
错误示例:
|
|
464
|
+
|
|
465
|
+
<!-- prettier-ignore -->
|
|
466
|
+
````html
|
|
467
|
+
<label>Name</label><input>
|
|
468
|
+
````
|
|
469
|
+
|
|
470
|
+
正确示例:
|
|
471
|
+
|
|
472
|
+
<!-- prettier-ignore -->
|
|
473
|
+
````html
|
|
474
|
+
<label for="name">Name</label><input id="name">
|
|
475
|
+
````
|
|
476
|
+
|
|
477
|
+
### `@angular-eslint/template/mouse-events-have-key-events`
|
|
478
|
+
|
|
479
|
+
`mouseover` 和 `mouseout` 行为需要对应键盘焦点事件,保持输入方式等价。
|
|
480
|
+
|
|
481
|
+
- 生效级别与范围:error: Angular HTML
|
|
482
|
+
- 自动修复:不支持或上游未声明
|
|
483
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/mouse-events-have-key-events.md)
|
|
484
|
+
- 常见报告:`'{{mouseEvent}}' must be accompanied by '{{keyEvent}}' for accessibility (https://www.w3.org/WAI/WCAG21/Understanding/keyboard)`
|
|
485
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
486
|
+
|
|
487
|
+
错误示例:
|
|
488
|
+
|
|
489
|
+
<!-- prettier-ignore -->
|
|
490
|
+
````html
|
|
491
|
+
<div (mouseover)="showDetails()">Details</div>
|
|
492
|
+
````
|
|
493
|
+
|
|
494
|
+
正确示例:
|
|
495
|
+
|
|
496
|
+
<!-- prettier-ignore -->
|
|
497
|
+
````html
|
|
498
|
+
<div (mouseover)="showDetails()" (focus)="showDetails()" tabindex="0">Details</div>
|
|
499
|
+
````
|
|
500
|
+
|
|
501
|
+
### `@angular-eslint/template/no-autofocus`
|
|
502
|
+
|
|
503
|
+
`autofocus` 会突然移动焦点并干扰读屏流程,默认禁止。
|
|
504
|
+
|
|
505
|
+
- 生效级别与范围:error: Angular HTML
|
|
506
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
507
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/no-autofocus.md)
|
|
508
|
+
- 常见报告:`The 'autofocus' attribute should not be used, as it reduces usability and accessibility for users`
|
|
509
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
510
|
+
|
|
511
|
+
错误示例:
|
|
512
|
+
|
|
513
|
+
<!-- prettier-ignore -->
|
|
514
|
+
````html
|
|
515
|
+
<input autofocus>
|
|
516
|
+
````
|
|
517
|
+
|
|
518
|
+
正确示例:
|
|
519
|
+
|
|
520
|
+
<!-- prettier-ignore -->
|
|
521
|
+
````html
|
|
522
|
+
<input>
|
|
523
|
+
````
|
|
524
|
+
|
|
525
|
+
### `@angular-eslint/template/no-distracting-elements`
|
|
526
|
+
|
|
527
|
+
禁止 `marquee`、`blink` 等干扰性元素,避免可读性和可访问性问题。
|
|
528
|
+
|
|
529
|
+
- 生效级别与范围:error: Angular HTML
|
|
530
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
531
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/no-distracting-elements.md)
|
|
532
|
+
- 常见报告:`Do not use <{{element}}> elements as they can create visual accessibility issues and are deprecated`
|
|
533
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
534
|
+
|
|
535
|
+
错误示例:
|
|
536
|
+
|
|
537
|
+
<!-- prettier-ignore -->
|
|
538
|
+
````html
|
|
539
|
+
<marquee>News</marquee>
|
|
540
|
+
````
|
|
541
|
+
|
|
542
|
+
正确示例:
|
|
543
|
+
|
|
544
|
+
<!-- prettier-ignore -->
|
|
545
|
+
````html
|
|
546
|
+
<p aria-live="polite">News</p>
|
|
547
|
+
````
|
|
548
|
+
|
|
549
|
+
### `@angular-eslint/template/no-negated-async`
|
|
550
|
+
|
|
551
|
+
对 `async` pipe 结果直接取反会让初始 `null` 状态产生反直觉分支。
|
|
552
|
+
|
|
553
|
+
- 生效级别与范围:error: Angular HTML
|
|
554
|
+
- 自动修复:不支持或上游未声明
|
|
555
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/no-negated-async.md)
|
|
556
|
+
- 常见报告:`Async pipe results should not be negated. Use '(observable | async) === false', '(observable | async) === null', or '(observable | async) === undefined' to check its value instead`;`Values used with the async pipe should not be negated.`;`Compare with 'false'`
|
|
557
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
558
|
+
|
|
559
|
+
错误示例:
|
|
560
|
+
|
|
561
|
+
<!-- prettier-ignore -->
|
|
562
|
+
````html
|
|
563
|
+
<p *ngIf="!(ready$ | async)">Loading</p>
|
|
564
|
+
````
|
|
565
|
+
|
|
566
|
+
正确示例:
|
|
567
|
+
|
|
568
|
+
<!-- prettier-ignore -->
|
|
569
|
+
````html
|
|
570
|
+
<p *ngIf="(ready$ | async) === false">Loading</p>
|
|
571
|
+
````
|
|
572
|
+
|
|
573
|
+
### `@angular-eslint/template/prefer-control-flow`
|
|
574
|
+
|
|
575
|
+
采用现代 `@if` 和 `@for` 控制流,与 Angular 推荐模板语法保持一致。
|
|
576
|
+
|
|
577
|
+
- 生效级别与范围:error: Angular HTML
|
|
578
|
+
- 自动修复:不支持或上游未声明
|
|
579
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/prefer-control-flow.md)
|
|
580
|
+
- 常见报告:`Use built-in control flow instead of directive {{name}}.`
|
|
581
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
582
|
+
|
|
583
|
+
错误示例:
|
|
584
|
+
|
|
585
|
+
<!-- prettier-ignore -->
|
|
586
|
+
````html
|
|
587
|
+
<p *ngIf="ready">Ready</p>
|
|
588
|
+
````
|
|
589
|
+
|
|
590
|
+
正确示例:
|
|
591
|
+
|
|
592
|
+
<!-- prettier-ignore -->
|
|
593
|
+
````html
|
|
594
|
+
@if (ready) { <p>Ready</p> }
|
|
595
|
+
````
|
|
596
|
+
|
|
597
|
+
### `@angular-eslint/template/role-has-required-aria`
|
|
598
|
+
|
|
599
|
+
ARIA role 必须提供该角色要求的属性,避免声明不完整的语义。
|
|
600
|
+
|
|
601
|
+
- 生效级别与范围:error: Angular HTML
|
|
602
|
+
- 自动修复:不支持或上游未声明
|
|
603
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/role-has-required-aria.md)
|
|
604
|
+
- 常见报告:`The {{element}} with role="{{role}}" does not have required ARIA properties: {{missingProps}}`;`Remove role '{{role}}'`
|
|
605
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
606
|
+
|
|
607
|
+
错误示例:
|
|
608
|
+
|
|
609
|
+
<!-- prettier-ignore -->
|
|
610
|
+
````html
|
|
611
|
+
<div role="checkbox">Enabled</div>
|
|
612
|
+
````
|
|
613
|
+
|
|
614
|
+
正确示例:
|
|
615
|
+
|
|
616
|
+
<!-- prettier-ignore -->
|
|
617
|
+
````html
|
|
618
|
+
<div role="checkbox" aria-checked="false" tabindex="0">Enabled</div>
|
|
619
|
+
````
|
|
620
|
+
|
|
621
|
+
### `@angular-eslint/template/table-scope`
|
|
622
|
+
|
|
623
|
+
`scope` 只能用于表头 `<th>`,避免在普通单元格上声明无效的表头范围。
|
|
624
|
+
|
|
625
|
+
- 生效级别与范围:error: Angular HTML
|
|
626
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
627
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/table-scope.md)
|
|
628
|
+
- 常见报告:`The 'scope' attribute should only be on the '<th>' element`
|
|
629
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
630
|
+
|
|
631
|
+
错误示例:
|
|
632
|
+
|
|
633
|
+
<!-- prettier-ignore -->
|
|
634
|
+
````html
|
|
635
|
+
<td scope="col">Name</td>
|
|
636
|
+
````
|
|
637
|
+
|
|
638
|
+
正确示例:
|
|
639
|
+
|
|
640
|
+
<!-- prettier-ignore -->
|
|
641
|
+
````html
|
|
642
|
+
<th scope="col">Name</th>
|
|
643
|
+
````
|
|
644
|
+
|
|
645
|
+
### `@angular-eslint/template/valid-aria`
|
|
646
|
+
|
|
647
|
+
ARIA 属性名和值必须有效,避免浏览器静默忽略错误语义。
|
|
648
|
+
|
|
649
|
+
- 生效级别与范围:error: Angular HTML
|
|
650
|
+
- 自动修复:不支持或上游未声明
|
|
651
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin-template/docs/rules/valid-aria.md)
|
|
652
|
+
- 常见报告:`The '{{attribute}}' is an invalid ARIA attribute`;`The '{{attribute}}' has an invalid value. Check the valid values at https://raw.githack.com/w3c/aria/stable/#roles`;`Remove attribute '{{attribute}}'`
|
|
653
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
654
|
+
|
|
655
|
+
错误示例:
|
|
656
|
+
|
|
657
|
+
<!-- prettier-ignore -->
|
|
658
|
+
````html
|
|
659
|
+
<button aria-labl="Save">Save</button>
|
|
660
|
+
````
|
|
661
|
+
|
|
662
|
+
正确示例:
|
|
663
|
+
|
|
664
|
+
<!-- prettier-ignore -->
|
|
665
|
+
````html
|
|
666
|
+
<button aria-label="Save">Save</button>
|
|
667
|
+
````
|
|
668
|
+
|
|
669
|
+
### `@angular-eslint/use-lifecycle-interface`
|
|
670
|
+
|
|
671
|
+
生命周期接口让方法拼写和签名可由 TypeScript 验证;警告级别便于渐进补齐旧代码。
|
|
672
|
+
|
|
673
|
+
- 生效级别与范围:warn: Angular TypeScript
|
|
674
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
675
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/use-lifecycle-interface.md)
|
|
676
|
+
- 常见报告:`Lifecycle interface '{{interfaceName}}' should be implemented for method '{{methodName}}'. (https://angular.dev/style-guide#use-lifecycle-hook-interfaces)`
|
|
677
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
678
|
+
|
|
679
|
+
错误示例:
|
|
680
|
+
|
|
681
|
+
<!-- prettier-ignore -->
|
|
682
|
+
````ts
|
|
683
|
+
import { Component } from "@angular/core";
|
|
684
|
+
@Component({ selector: "app-page", template: `` })
|
|
685
|
+
class PageComponent { ngOnInit(): void { console.log("initialized"); } }
|
|
686
|
+
````
|
|
687
|
+
|
|
688
|
+
正确示例:
|
|
689
|
+
|
|
690
|
+
<!-- prettier-ignore -->
|
|
691
|
+
````ts
|
|
692
|
+
import { Component, OnInit } from "@angular/core";
|
|
693
|
+
@Component({ selector: "app-page", template: `` })
|
|
694
|
+
class PageComponent implements OnInit { ngOnInit(): void { console.log("initialized"); } }
|
|
695
|
+
````
|
|
696
|
+
|
|
697
|
+
### `@angular-eslint/use-pipe-transform-interface`
|
|
698
|
+
|
|
699
|
+
Pipe 类实现接口后可由 TypeScript 检查 `transform` 签名,避免运行时才发现不一致。
|
|
700
|
+
|
|
701
|
+
- 生效级别与范围:error: Angular TypeScript
|
|
702
|
+
- 自动修复:支持;执行前仍应检查语义和差异
|
|
703
|
+
- 规则来源:[官方文档](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/use-pipe-transform-interface.md)
|
|
704
|
+
- 常见报告:`Pipes should implement 'PipeTransform' interface`
|
|
705
|
+
- 示例类型:仓库显式规则的直接代码示例
|
|
706
|
+
|
|
707
|
+
错误示例:
|
|
708
|
+
|
|
709
|
+
<!-- prettier-ignore -->
|
|
710
|
+
````ts
|
|
711
|
+
@Pipe({ name: "label" })
|
|
712
|
+
class LabelPipe { transform(value: string): string { return value.trim(); } }
|
|
713
|
+
````
|
|
714
|
+
|
|
715
|
+
正确示例:
|
|
716
|
+
|
|
717
|
+
<!-- prettier-ignore -->
|
|
718
|
+
````ts
|
|
719
|
+
@Pipe({ name: "label" })
|
|
720
|
+
class LabelPipe implements PipeTransform { transform(value: string): string { return value.trim(); } }
|
|
721
|
+
````
|