@agilebot/eslint-config 0.1.6 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -5,13 +5,12 @@
5
5
  ```bash
6
6
  npm install --save-dev eslint \
7
7
  @agilebot/eslint-config \
8
- @agilebot/eslint-plugin \
9
- @agilebot/eslint-utils
8
+ @agilebot/eslint-plugin
10
9
  ```
11
10
 
12
11
  ```js
13
12
  // .eslintrc.js
14
- const { agilebot } = require('@agilebot/eslint-utils');
13
+ const { agilebot } = require('@agilebot/eslint-config');
15
14
 
16
15
  module.exports = agilebot(__dirname);
17
16
  ```
@@ -0,0 +1,13 @@
1
+ import { Linter } from 'eslint';
2
+
3
+ interface FactoryOptions {
4
+ devDependencies?: string[];
5
+ cspellWords?: string[];
6
+ config?: Linter.Config;
7
+ react?: boolean;
8
+ vue?: number;
9
+ godaddy?: boolean;
10
+ }
11
+ declare function factory(root: string, options?: FactoryOptions): Linter.BaseConfig;
12
+
13
+ export { factory as agilebot };
package/dist/index.js ADDED
@@ -0,0 +1,638 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ agilebot: () => factory
34
+ });
35
+ module.exports = __toCommonJS(src_exports);
36
+
37
+ // src/factory.ts
38
+ var import_node_assert = __toESM(require("assert"));
39
+ var import_eslint_utils3 = require("@agilebot/eslint-utils");
40
+ var import_fast_glob = require("fast-glob");
41
+
42
+ // src/configs/env.ts
43
+ function env() {
44
+ return {
45
+ env: {
46
+ browser: true,
47
+ node: true,
48
+ es6: true,
49
+ mocha: true,
50
+ jest: true,
51
+ jasmine: true
52
+ }
53
+ };
54
+ }
55
+
56
+ // src/configs/standard.ts
57
+ function standard() {
58
+ return {
59
+ extends: ["love"],
60
+ rules: {
61
+ "no-alert": "error",
62
+ // 避免使用同步方法
63
+ "n/no-sync": "error",
64
+ // 尽量使用fs.promises而不是fs
65
+ "n/prefer-promises/fs": "error",
66
+ "arrow-body-style": "off",
67
+ curly: "error",
68
+ // 找出TODO注释,以便后期修复
69
+ "no-warning-comments": [
70
+ "warn",
71
+ {
72
+ terms: ["todo", "fixme"]
73
+ }
74
+ ],
75
+ // 路径拼接使用path.join,而不是直接使用加号
76
+ "n/no-path-concat": "error"
77
+ }
78
+ };
79
+ }
80
+
81
+ // src/configs/ts.ts
82
+ function ts() {
83
+ return {
84
+ plugins: ["@typescript-eslint", "@stylistic"],
85
+ rules: {
86
+ "@typescript-eslint/no-unused-vars": "warn",
87
+ // 如果没用模板字符串,避免使用反引号
88
+ "@stylistic/quotes": ["error", "single", { avoidEscape: true }],
89
+ // 优先使用interface而不是type
90
+ "@typescript-eslint/consistent-type-definitions": "error",
91
+ // The `@typescript-eslint/naming-convention` rule allows `leadingUnderscore` and `trailingUnderscore` settings.
92
+ // However, the existing `no-underscore-dangle` rule already takes care of this.
93
+ "@typescript-eslint/naming-convention": [
94
+ "error",
95
+ // Allow camelCase variables (23.2), PascalCase variables (23.8), and UPPER_CASE variables (23.10)
96
+ {
97
+ selector: "variable",
98
+ format: ["camelCase", "PascalCase", "UPPER_CASE"],
99
+ filter: {
100
+ regex: "^(__dirname|__filename)$",
101
+ match: false
102
+ }
103
+ },
104
+ // Allow camelCase functions (23.2), and PascalCase functions (23.8)
105
+ {
106
+ selector: "function",
107
+ format: ["camelCase", "PascalCase"]
108
+ },
109
+ // Airbnb recommends PascalCase for classes (23.3),
110
+ // and although Airbnb does not make TypeScript recommendations,
111
+ // we are assuming this rule would similarly apply to anything "type like",
112
+ // including interfaces, type aliases, and enums
113
+ {
114
+ selector: "typeLike",
115
+ format: ["PascalCase"]
116
+ },
117
+ {
118
+ selector: "parameter",
119
+ format: ["camelCase"],
120
+ leadingUnderscore: "allow"
121
+ },
122
+ {
123
+ selector: "method",
124
+ format: ["camelCase", "PascalCase"]
125
+ },
126
+ {
127
+ selector: "typeProperty",
128
+ format: ["camelCase"]
129
+ },
130
+ {
131
+ selector: "enumMember",
132
+ format: ["PascalCase", "UPPER_CASE"]
133
+ }
134
+ ],
135
+ // 禁止没有必要的初始化
136
+ "@typescript-eslint/no-inferrable-types": "error",
137
+ // 函数中未使用await,函数签名不要加async
138
+ "@typescript-eslint/require-await": "error",
139
+ // 没有必要的类型as
140
+ "@typescript-eslint/no-unnecessary-type-assertion": "error",
141
+ // 数组用T[]而不是Array<T>
142
+ "@typescript-eslint/array-type": ["error", { default: "array" }],
143
+ // Promise必须加await或void
144
+ "@typescript-eslint/no-misused-promises": [
145
+ "error",
146
+ {
147
+ checksVoidReturn: false
148
+ }
149
+ ],
150
+ // 以下是关闭的规则
151
+ "@typescript-eslint/strict-boolean-expressions": "off",
152
+ "@typescript-eslint/explicit-function-return-type": "off",
153
+ "@typescript-eslint/restrict-template-expressions": "off",
154
+ "@typescript-eslint/no-non-null-assertion": "off",
155
+ "@typescript-eslint/method-signature-style": "off",
156
+ "@typescript-eslint/consistent-type-assertions": "off",
157
+ "@typescript-eslint/no-extraneous-class": "off",
158
+ "@typescript-eslint/no-confusing-void-expression": "off",
159
+ "@typescript-eslint/explicit-member-accessibility": "off",
160
+ "@typescript-eslint/unbound-method": "off",
161
+ "@typescript-eslint/no-unsafe-argument": "off"
162
+ }
163
+ };
164
+ }
165
+
166
+ // src/configs/promise.ts
167
+ function promise() {
168
+ return {
169
+ plugins: ["promise"],
170
+ rules: {
171
+ "promise/no-nesting": "error",
172
+ "promise/no-promise-in-callback": "error",
173
+ "promise/param-names": "error",
174
+ "promise/no-multiple-resolved": "error",
175
+ "promise/no-return-in-finally": "error"
176
+ }
177
+ };
178
+ }
179
+
180
+ // src/configs/import.ts
181
+ var import_node_path = __toESM(require("path"));
182
+ var import_node_fs = __toESM(require("fs"));
183
+ var import_eslint_utils = require("@agilebot/eslint-utils");
184
+ function eslintImport(packageDir, devDependencies) {
185
+ const rootDir = (0, import_eslint_utils.findRootDir)(__dirname);
186
+ const pkg = require(import_node_path.default.join(packageDir, "package.json"));
187
+ const tmpPkg = {
188
+ name: `${pkg.name}/tmp`,
189
+ dependencies: {
190
+ [pkg.name]: "*"
191
+ }
192
+ };
193
+ const tmpPkgSafeName = tmpPkg.name.replaceAll("/", "__");
194
+ const cacheDir = (0, import_eslint_utils.findCacheDir)(rootDir);
195
+ const tmpPkgDir = import_node_path.default.join(cacheDir, "tmp-pkg", tmpPkgSafeName);
196
+ if (!import_node_fs.default.existsSync(tmpPkgDir)) {
197
+ import_node_fs.default.mkdirSync(tmpPkgDir, { recursive: true });
198
+ }
199
+ const tmpPkgJson = JSON.stringify(tmpPkg, null, 2);
200
+ import_node_fs.default.writeFileSync(import_node_path.default.join(tmpPkgDir, "package.json"), tmpPkgJson);
201
+ return {
202
+ plugins: ["import", "no-relative-import-paths"],
203
+ extends: ["plugin:import/recommended", "plugin:import/typescript"],
204
+ rules: {
205
+ "import/no-unresolved": "error",
206
+ "import/no-named-as-default-member": "off",
207
+ "import/no-named-as-default": "off",
208
+ "import/no-useless-path-segments": [
209
+ "error",
210
+ {
211
+ noUselessIndex: true
212
+ }
213
+ ],
214
+ "import/no-cycle": "error",
215
+ "import/newline-after-import": "error",
216
+ "import/first": "error",
217
+ "import/no-import-module-exports": "error",
218
+ "import/no-anonymous-default-export": [
219
+ "error",
220
+ {
221
+ allowArray: true,
222
+ allowObject: true
223
+ }
224
+ ],
225
+ "import/no-extraneous-dependencies": [
226
+ "error",
227
+ {
228
+ packageDir: [packageDir, tmpPkgDir, rootDir],
229
+ devDependencies: [
230
+ "test/**/*",
231
+ "tests/**/*",
232
+ "**/__tests__/**",
233
+ "**/*.test.{ts,tsx}",
234
+ "**/*.config.{ts,js,cjs,mjs,mts,cts}",
235
+ "**/.storybook/**",
236
+ "**/*.stories.{ts,tsx}",
237
+ "**/scripts/*.{ts,mts}",
238
+ ...devDependencies ?? []
239
+ ],
240
+ includeInternal: true
241
+ }
242
+ ],
243
+ "import/order": [
244
+ "error",
245
+ {
246
+ groups: [
247
+ "builtin",
248
+ "external",
249
+ "internal",
250
+ "parent",
251
+ "sibling",
252
+ "index",
253
+ "object"
254
+ ],
255
+ pathGroups: [
256
+ {
257
+ pattern: `${pkg.name}/**`,
258
+ group: "parent",
259
+ position: "after"
260
+ }
261
+ ],
262
+ "newlines-between": "never",
263
+ distinctGroup: false
264
+ }
265
+ ],
266
+ "no-relative-import-paths/no-relative-import-paths": [
267
+ "warn",
268
+ { allowSameFolder: true }
269
+ ]
270
+ },
271
+ settings: {
272
+ "import/parsers": {
273
+ "@typescript-eslint/parser": [".ts", ".tsx"]
274
+ },
275
+ "import/resolver": {
276
+ typescript: {
277
+ alwaysTryTypes: true
278
+ }
279
+ }
280
+ }
281
+ };
282
+ }
283
+
284
+ // src/configs/unicorn.ts
285
+ function unicorn() {
286
+ return {
287
+ plugins: ["unicorn"],
288
+ extends: ["plugin:unicorn/recommended"],
289
+ rules: {
290
+ // unicorn默认规则太严格,屏蔽以下
291
+ "unicorn/filename-case": "off",
292
+ "unicorn/import-style": "off",
293
+ "unicorn/prefer-at": "off",
294
+ "unicorn/prevent-abbreviations": "off",
295
+ "unicorn/prefer-date-now": "off",
296
+ "unicorn/no-process-exit": "off",
297
+ "unicorn/prefer-module": "off",
298
+ "unicorn/no-null": "off",
299
+ "unicorn/prefer-top-level-await": "off",
300
+ "unicorn/consistent-function-scoping": "off",
301
+ "unicorn/numeric-separators-style": "off",
302
+ "unicorn/prefer-optional-catch-binding": "off",
303
+ "unicorn/no-negated-condition": "off",
304
+ "unicorn/switch-case-braces": "off",
305
+ "unicorn/no-array-for-each": "off",
306
+ "unicorn/prefer-ternary": "off",
307
+ "unicorn/better-regex": "off",
308
+ "unicorn/error-message": "off",
309
+ "unicorn/no-object-as-default-parameter": "off",
310
+ "unicorn/no-array-push-push": "off",
311
+ "unicorn/no-useless-undefined": "off",
312
+ "unicorn/prefer-blob-reading-methods": "off",
313
+ "unicorn/catch-error-name": [
314
+ "error",
315
+ {
316
+ name: "err"
317
+ }
318
+ ]
319
+ }
320
+ };
321
+ }
322
+
323
+ // src/configs/react.ts
324
+ function react() {
325
+ return {
326
+ plugins: ["react", "react-hooks", "jsx-a11y"],
327
+ extends: [
328
+ "plugin:react/recommended",
329
+ "plugin:react-hooks/recommended",
330
+ "plugin:react-prefer-function-component/recommended",
331
+ "plugin:jsx-a11y/recommended"
332
+ ],
333
+ rules: {
334
+ // 禁止没必要的Fragment,除了<>{foo}</>
335
+ "react/jsx-no-useless-fragment": ["error", { allowExpressions: true }],
336
+ // 优先使用<>而不是<Fragment>
337
+ "react/jsx-fragments": "error",
338
+ "react/jsx-handler-names": [
339
+ "error",
340
+ {
341
+ eventHandlerPrefix: "handle",
342
+ eventHandlerPropPrefix: "on",
343
+ checkLocalVariables: true
344
+ }
345
+ ],
346
+ // useState必须以[example, setExample]命名
347
+ "react/hook-use-state": "error",
348
+ // 避免使用数组的 index 来作为 key 属性的值
349
+ "react/no-array-index-key": "error",
350
+ "react/self-closing-comp": "error",
351
+ // 组件命名符合帕斯卡
352
+ "react/jsx-pascal-case": [
353
+ "error",
354
+ {
355
+ allowNamespace: true
356
+ }
357
+ ],
358
+ // 布尔属性如果为true,省略值
359
+ "react/jsx-boolean-value": "error",
360
+ // 已经有ts校验,此规则没有必要,会与带静态属性的Functional Component冲突
361
+ "react/prop-types": "off",
362
+ // <App prop={'Hello'} />没必要,使用<App prop="Hello" />
363
+ "react/jsx-curly-brace-presence": [
364
+ "error",
365
+ {
366
+ props: "never",
367
+ children: "never",
368
+ propElementValues: "always"
369
+ }
370
+ ],
371
+ // 禁止声明未使用的props
372
+ "react/no-unused-prop-types": "error",
373
+ // img之类的void元素不应该有children
374
+ "react/void-dom-elements-no-children": "error",
375
+ "jsx-a11y/click-events-have-key-events": "off",
376
+ "jsx-a11y/no-static-element-interactions": "off",
377
+ "jsx-a11y/alt-text": "off"
378
+ },
379
+ settings: {
380
+ react: {
381
+ version: "detect"
382
+ }
383
+ }
384
+ };
385
+ }
386
+
387
+ // src/configs/vue.ts
388
+ function vue(version) {
389
+ return {
390
+ extends: [
391
+ version === 3 ? "plugin:vue/vue3-recommended" : "plugin:vue/recommended"
392
+ ]
393
+ };
394
+ }
395
+
396
+ // src/configs/jsdoc.ts
397
+ function jsdoc() {
398
+ return {
399
+ plugins: ["jsdoc"],
400
+ extends: ["plugin:jsdoc/recommended-typescript-error"],
401
+ rules: {
402
+ // 禁止有空行
403
+ "jsdoc/no-blank-block-descriptions": "error",
404
+ "jsdoc/no-blank-blocks": "error",
405
+ "jsdoc/require-returns": "off",
406
+ // @return注释不是很有必要
407
+ "jsdoc/require-returns-type": "off",
408
+ // 每行注释都有星号
409
+ "jsdoc/require-asterisk-prefix": "error"
410
+ }
411
+ };
412
+ }
413
+
414
+ // src/configs/lodash.ts
415
+ function lodash() {
416
+ return {
417
+ // lodash一些方法可能影响性能,如forEach等,优先使用js的原生方法
418
+ extends: ["plugin:you-dont-need-lodash-underscore/compatible"]
419
+ };
420
+ }
421
+
422
+ // src/configs/eslint.ts
423
+ var import_eslint_utils2 = require("@agilebot/eslint-utils");
424
+ function eslint() {
425
+ return {
426
+ plugins: ["eslint-comments", "file-progress"],
427
+ rules: {
428
+ // 禁止未使用的eslint-disable注释
429
+ "eslint-comments/no-unused-disable": "error",
430
+ // 禁止无限制的eslint-disable注释
431
+ "eslint-comments/no-unlimited-disable": "error",
432
+ // 禁止重复的eslint-disable注释
433
+ "eslint-comments/no-duplicate-disable": "error",
434
+ // 禁止聚合的eslint-enable注释
435
+ "eslint-comments/no-aggregating-enable": "error",
436
+ // 须说明原因eslint-disable
437
+ "eslint-comments/require-description": [
438
+ "error",
439
+ {
440
+ ignore: ["eslint-env", "exported", "global", "globals"]
441
+ }
442
+ ],
443
+ "file-progress/activate": (0, import_eslint_utils2.isCI)() ? "off" : "warn"
444
+ }
445
+ };
446
+ }
447
+
448
+ // src/configs/deprecation.ts
449
+ function deprecation() {
450
+ return {
451
+ plugins: ["deprecation"],
452
+ rules: {
453
+ // 禁止使用带有deprecation标记的方法或属性
454
+ "deprecation/deprecation": "error"
455
+ }
456
+ };
457
+ }
458
+
459
+ // src/configs/cspell.ts
460
+ function cspell(words) {
461
+ return {
462
+ plugins: ["@cspell"],
463
+ rules: {
464
+ "@cspell/spellchecker": [
465
+ "warn",
466
+ {
467
+ checkComments: false,
468
+ autoFix: false,
469
+ cspell: {
470
+ words
471
+ }
472
+ }
473
+ ]
474
+ }
475
+ };
476
+ }
477
+
478
+ // src/configs/agilebot.ts
479
+ function agilebot() {
480
+ return {
481
+ extends: ["plugin:@agilebot/recommended"],
482
+ plugins: ["react-hooks"],
483
+ rules: {
484
+ "react-hooks/exhaustive-deps": "off",
485
+ "@agilebot/react/better-exhaustive-deps": [
486
+ "warn",
487
+ {
488
+ checkMemoizedVariableIsStatic: true,
489
+ staticHooks: {
490
+ "useIpc.*": {
491
+ value: true,
492
+ regexp: true
493
+ },
494
+ useDialog: true,
495
+ useSnackbar: true,
496
+ useForm: true,
497
+ "use.*Store": {
498
+ value: true,
499
+ regexp: true
500
+ }
501
+ }
502
+ }
503
+ ]
504
+ }
505
+ };
506
+ }
507
+
508
+ // src/configs/prettier.ts
509
+ function prettier() {
510
+ return {
511
+ plugins: ["prettier"],
512
+ extends: ["plugin:prettier/recommended"],
513
+ rules: {
514
+ "prettier/prettier": [
515
+ "error",
516
+ {
517
+ endOfLine: "auto"
518
+ }
519
+ ]
520
+ }
521
+ };
522
+ }
523
+
524
+ // src/configs/godaddy.ts
525
+ function godaddy() {
526
+ return {
527
+ extends: ["godaddy"],
528
+ rules: {
529
+ "quote-props": "off",
530
+ "linebreak-style": "off",
531
+ complexity: "off",
532
+ "max-statements": "off",
533
+ "id-length": "off",
534
+ "default-case": "off",
535
+ "valid-jsdoc": "off",
536
+ "generator-star-spacing": "off",
537
+ "max-params": "off",
538
+ "max-depth": "off",
539
+ "no-undefined": "off",
540
+ "no-process-env": "off",
541
+ "no-sync": "off"
542
+ }
543
+ };
544
+ }
545
+
546
+ // src/factory.ts
547
+ function factory(root, options) {
548
+ import_node_assert.default.ok(root, "root option is required");
549
+ if (options?.godaddy) {
550
+ return (0, import_eslint_utils3.mergeESLintConfig)(
551
+ godaddy(),
552
+ prettier(),
553
+ unicorn(),
554
+ eslint(),
555
+ eslintImport(root, options?.devDependencies),
556
+ options?.config ?? {}
557
+ );
558
+ }
559
+ const config = {
560
+ overrides: [
561
+ {
562
+ files: [
563
+ "*.ts",
564
+ "*.tsx",
565
+ "*.cts",
566
+ "*.mts",
567
+ "*.js",
568
+ "*.jsx",
569
+ "*.cjs",
570
+ "*.mjs",
571
+ "*.vue"
572
+ ],
573
+ parser: !options?.vue ? "@typescript-eslint/parser" : "vue-eslint-parser",
574
+ parserOptions: {
575
+ parser: "@typescript-eslint/parser",
576
+ tsconfigRootDir: root
577
+ },
578
+ ...(0, import_eslint_utils3.mergeESLintConfig)(
579
+ env(),
580
+ standard(),
581
+ ts(),
582
+ promise(),
583
+ eslintImport(root, options?.devDependencies),
584
+ unicorn(),
585
+ options?.react ? react() : {},
586
+ options?.vue ? vue(options.vue) : {},
587
+ jsdoc(),
588
+ lodash(),
589
+ eslint(),
590
+ deprecation(),
591
+ cspell(options?.cspellWords ?? []),
592
+ agilebot(),
593
+ prettier(),
594
+ options?.config ?? {}
595
+ )
596
+ },
597
+ {
598
+ files: ["*.ts", "*.tsx"],
599
+ rules: {
600
+ "@typescript-eslint/explicit-member-accessibility": "error"
601
+ }
602
+ },
603
+ {
604
+ files: ["*.d.ts"],
605
+ rules: {
606
+ // .d.ts中支持导入ts文件中的类型
607
+ "@typescript-eslint/consistent-type-imports": "off",
608
+ // .d.ts中忽略属性命名规则
609
+ "@typescript-eslint/naming-convention": "off",
610
+ // .d.ts中忽略三斜线引用
611
+ "@typescript-eslint/triple-slash-reference": "off"
612
+ }
613
+ },
614
+ {
615
+ files: ["*.js", "*.jsx", "*.cjs"],
616
+ rules: {
617
+ "@typescript-eslint/no-var-requires": "off"
618
+ }
619
+ }
620
+ ]
621
+ };
622
+ const tsconfigFiles = (0, import_fast_glob.globSync)("tsconfig*.json", {
623
+ cwd: root
624
+ });
625
+ if (config.parserOptions) {
626
+ if (tsconfigFiles.length > 0) {
627
+ config.parserOptions.project = tsconfigFiles;
628
+ } else {
629
+ config.parserOptions.project = true;
630
+ }
631
+ }
632
+ return config;
633
+ }
634
+ // Annotate the CommonJS export names for ESM import in node:
635
+ 0 && (module.exports = {
636
+ agilebot
637
+ });
638
+ if (module.exports.default) module.exports = module.exports.default;
package/package.json CHANGED
@@ -1,11 +1,9 @@
1
1
  {
2
2
  "name": "@agilebot/eslint-config",
3
- "version": "0.1.6",
3
+ "version": "0.2.1",
4
4
  "description": "Agilebot's ESLint config",
5
- "bin": {
6
- "eslint-agilebot": "bin/eslint-agilebot"
7
- },
8
- "main": "lib",
5
+ "main": "dist",
6
+ "types": "dist/index.d.ts",
9
7
  "license": "MIT",
10
8
  "keywords": [
11
9
  "eslint",
@@ -39,18 +37,20 @@
39
37
  "eslint-plugin-react-hooks": "^4.6.0",
40
38
  "eslint-plugin-react-prefer-function-component": "^3.3.0",
41
39
  "eslint-plugin-unicorn": "^52.0.0",
42
- "eslint-plugin-you-dont-need-lodash-underscore": "^6.13.0"
40
+ "eslint-plugin-vue": "^9.25.0",
41
+ "eslint-plugin-you-dont-need-lodash-underscore": "^6.13.0",
42
+ "fast-glob": "^3.3.2",
43
+ "@agilebot/eslint-utils": "0.2.1"
43
44
  },
44
45
  "peerDependencies": {
45
46
  "@agilebot/eslint-plugin": "*",
46
- "@agilebot/eslint-utils": "*",
47
47
  "eslint": "^7.0.0 || ^8.0.0"
48
48
  },
49
49
  "files": [
50
- "lib",
51
- "bin"
50
+ "dist"
52
51
  ],
53
52
  "scripts": {
54
- "lint": "eslint lib --fix"
53
+ "build": "tsup",
54
+ "lint": "eslint src --fix"
55
55
  }
56
56
  }
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- require('../lib/cli')();
package/lib/cli.js DELETED
@@ -1,49 +0,0 @@
1
- const fs = require('node:fs');
2
- const path = require('node:path');
3
-
4
- module.exports = function cli(filename) {
5
- filename = filename || path.join(__dirname, 'index');
6
-
7
- const isEslint = /^\.eslint.*/;
8
- const cwd = process.cwd();
9
- const has = {
10
- fix: false,
11
- config: false
12
- };
13
-
14
- process.argv.forEach(function (arg) {
15
- has.fix = has.fix || arg === '--fix';
16
- has.config = has.config || arg === '-c' || arg === '--config';
17
- });
18
-
19
- if (!has.fix) {
20
- process.argv.splice(2, 0, '--fix');
21
- }
22
-
23
- //
24
- // Only force our config file if there is one not in the current
25
- // directory AND not specified by the command line.
26
- //
27
-
28
- // eslint-disable-next-line n/prefer-promises/fs -- Not available in Node.js 10
29
- fs.readdir(cwd, function (err, files) {
30
- if (err) {
31
- throw err;
32
- }
33
-
34
- has.config =
35
- has.config ||
36
- files.some(function (file) {
37
- return isEslint.test(file);
38
- });
39
-
40
- if (!has.config) {
41
- process.argv.splice(2, 0, '-c', require.resolve(filename));
42
- }
43
-
44
- const pkg = require.resolve('eslint/package.json');
45
- const bin = path.join(pkg, '..', 'bin', 'eslint.js');
46
-
47
- require(bin);
48
- });
49
- };
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- extends: ['plugin:@agilebot/recommended']
3
- };
@@ -1,12 +0,0 @@
1
- module.exports = {
2
- plugins: ['@cspell'],
3
- rules: {
4
- '@cspell/spellchecker': [
5
- 'warn',
6
- {
7
- checkComments: false,
8
- autoFix: false
9
- }
10
- ]
11
- }
12
- };
@@ -1,7 +0,0 @@
1
- module.exports = {
2
- plugins: ['deprecation'],
3
- rules: {
4
- // 禁止使用带有deprecation标记的方法或属性
5
- 'deprecation/deprecation': 'error'
6
- }
7
- };
@@ -1,10 +0,0 @@
1
- module.exports = {
2
- env: {
3
- browser: true,
4
- node: true,
5
- es6: true,
6
- mocha: true,
7
- jest: true,
8
- jasmine: true
9
- }
10
- };
@@ -1,23 +0,0 @@
1
- const { isCI } = require('@agilebot/eslint-utils');
2
-
3
- module.exports = {
4
- plugins: ['eslint-comments', 'file-progress'],
5
- rules: {
6
- // 禁止未使用的eslint-disable注释
7
- 'eslint-comments/no-unused-disable': 'error',
8
- // 禁止无限制的eslint-disable注释
9
- 'eslint-comments/no-unlimited-disable': 'error',
10
- // 禁止重复的eslint-disable注释
11
- 'eslint-comments/no-duplicate-disable': 'error',
12
- // 禁止聚合的eslint-enable注释
13
- 'eslint-comments/no-aggregating-enable': 'error',
14
- // 须说明原因eslint-disable
15
- 'eslint-comments/require-description': [
16
- 'error',
17
- {
18
- ignore: ['eslint-env', 'exported', 'global', 'globals']
19
- }
20
- ],
21
- 'file-progress/activate': isCI() ? 'off' : 'warn'
22
- }
23
- };
@@ -1,19 +0,0 @@
1
- // config for eslint plugins, DO NOT use for ts
2
- module.exports = {
3
- extends: ['godaddy'],
4
- rules: {
5
- 'quote-props': 'off',
6
- 'linebreak-style': 'off',
7
- complexity: 'off',
8
- 'max-statements': 'off',
9
- 'id-length': 'off',
10
- 'default-case': 'off',
11
- 'valid-jsdoc': 'off',
12
- 'generator-star-spacing': 'off',
13
- 'max-params': 'off',
14
- 'max-depth': 'off',
15
- 'no-undefined': 'off',
16
- 'no-process-env': 'off',
17
- 'no-sync': 'off'
18
- }
19
- };
@@ -1,40 +0,0 @@
1
- module.exports = {
2
- plugins: ['import', 'no-relative-import-paths'],
3
- extends: ['plugin:import/recommended', 'plugin:import/typescript'],
4
- rules: {
5
- 'import/no-unresolved': 'error',
6
- 'import/no-named-as-default-member': 'off',
7
- 'import/no-named-as-default': 'off',
8
- 'import/no-useless-path-segments': [
9
- 'error',
10
- {
11
- noUselessIndex: true
12
- }
13
- ],
14
- 'import/no-cycle': 'error',
15
- 'import/newline-after-import': 'error',
16
- 'import/first': 'error',
17
- 'import/no-import-module-exports': 'error',
18
- 'import/no-anonymous-default-export': [
19
- 'error',
20
- {
21
- allowArray: true,
22
- allowObject: true
23
- }
24
- ],
25
- 'no-relative-import-paths/no-relative-import-paths': [
26
- 'warn',
27
- { allowSameFolder: true }
28
- ]
29
- },
30
- settings: {
31
- 'import/parsers': {
32
- '@typescript-eslint/parser': ['.ts', '.tsx']
33
- },
34
- 'import/resolver': {
35
- typescript: {
36
- alwaysTryTypes: true
37
- }
38
- }
39
- }
40
- };
@@ -1,14 +0,0 @@
1
- module.exports = {
2
- plugins: ['jsdoc'],
3
- extends: ['plugin:jsdoc/recommended-typescript-error'],
4
- rules: {
5
- // 禁止有空行
6
- 'jsdoc/no-blank-block-descriptions': 'error',
7
- 'jsdoc/no-blank-blocks': 'error',
8
- 'jsdoc/require-returns': 'off',
9
- // @return注释不是很有必要
10
- 'jsdoc/require-returns-type': 'off',
11
- // 每行注释都有星号
12
- 'jsdoc/require-asterisk-prefix': 'error'
13
- }
14
- };
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- // lodash一些方法可能影响性能,如forEach等,优先使用js的原生方法
3
- extends: ['plugin:you-dont-need-lodash-underscore/compatible']
4
- };
@@ -1,12 +0,0 @@
1
- module.exports = {
2
- plugins: ['prettier'],
3
- extends: ['plugin:prettier/recommended'],
4
- rules: {
5
- 'prettier/prettier': [
6
- 'error',
7
- {
8
- endOfLine: 'auto'
9
- }
10
- ]
11
- }
12
- };
@@ -1,10 +0,0 @@
1
- module.exports = {
2
- plugins: ['promise'],
3
- rules: {
4
- 'promise/no-nesting': 'error',
5
- 'promise/no-promise-in-callback': 'error',
6
- 'promise/param-names': 'error',
7
- 'promise/no-multiple-resolved': 'error',
8
- 'promise/no-return-in-finally': 'error'
9
- }
10
- };
@@ -1,60 +0,0 @@
1
- module.exports = {
2
- plugins: ['react', 'react-hooks', 'jsx-a11y'],
3
- extends: [
4
- 'plugin:react/recommended',
5
- 'plugin:react-hooks/recommended',
6
- 'plugin:react-prefer-function-component/recommended',
7
- 'plugin:jsx-a11y/recommended'
8
- ],
9
- rules: {
10
- // 禁止没必要的Fragment,除了<>{foo}</>
11
- 'react/jsx-no-useless-fragment': ['error', { allowExpressions: true }],
12
- // 优先使用<>而不是<Fragment>
13
- 'react/jsx-fragments': 'error',
14
- 'react/jsx-handler-names': [
15
- 'error',
16
- {
17
- eventHandlerPrefix: 'handle',
18
- eventHandlerPropPrefix: 'on',
19
- checkLocalVariables: true
20
- }
21
- ],
22
- // useState必须以[example, setExample]命名
23
- 'react/hook-use-state': 'error',
24
- // 避免使用数组的 index 来作为 key 属性的值
25
- 'react/no-array-index-key': 'error',
26
- 'react/self-closing-comp': 'error',
27
- // 组件命名符合帕斯卡
28
- 'react/jsx-pascal-case': [
29
- 'error',
30
- {
31
- allowNamespace: true
32
- }
33
- ],
34
- // 布尔属性如果为true,省略值
35
- 'react/jsx-boolean-value': 'error',
36
- // 已经有ts校验,此规则没有必要,会与带静态属性的Functional Component冲突
37
- 'react/prop-types': 'off',
38
- // <App prop={'Hello'} />没必要,使用<App prop="Hello" />
39
- 'react/jsx-curly-brace-presence': [
40
- 'error',
41
- {
42
- props: 'never',
43
- children: 'never',
44
- propElementValues: 'always'
45
- }
46
- ],
47
- // 禁止声明未使用的props
48
- 'react/no-unused-prop-types': 'error',
49
- // img之类的void元素不应该有children
50
- 'react/void-dom-elements-no-children': 'error',
51
- 'jsx-a11y/click-events-have-key-events': 'off',
52
- 'jsx-a11y/no-static-element-interactions': 'off',
53
- 'jsx-a11y/alt-text': 'off'
54
- },
55
- settings: {
56
- react: {
57
- version: 'detect'
58
- }
59
- }
60
- };
@@ -1,21 +0,0 @@
1
- module.exports = {
2
- extends: ['love'],
3
- rules: {
4
- 'no-alert': 'error',
5
- // 避免使用同步方法
6
- 'n/no-sync': 'error',
7
- // 尽量使用fs.promises而不是fs
8
- 'n/prefer-promises/fs': 'error',
9
- 'arrow-body-style': 'error',
10
- curly: 'error',
11
- // 找出TODO注释,以便后期修复
12
- 'no-warning-comments': [
13
- 'warn',
14
- {
15
- terms: ['todo', 'fixme']
16
- }
17
- ],
18
- // 路径拼接使用path.join,而不是直接使用加号
19
- 'n/no-path-concat': 'error'
20
- }
21
- };
package/lib/configs/ts.js DELETED
@@ -1,81 +0,0 @@
1
- module.exports = {
2
- plugins: ['@typescript-eslint', '@stylistic'],
3
- rules: {
4
- '@typescript-eslint/no-unused-vars': 'warn',
5
- // 如果没用模板字符串,避免使用反引号
6
- '@stylistic/quotes': ['error', 'single', { avoidEscape: true }],
7
- // 优先使用interface而不是type
8
- '@typescript-eslint/consistent-type-definitions': 'error',
9
- // The `@typescript-eslint/naming-convention` rule allows `leadingUnderscore` and `trailingUnderscore` settings.
10
- // However, the existing `no-underscore-dangle` rule already takes care of this.
11
- '@typescript-eslint/naming-convention': [
12
- 'error',
13
- // Allow camelCase variables (23.2), PascalCase variables (23.8), and UPPER_CASE variables (23.10)
14
- {
15
- selector: 'variable',
16
- format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
17
- filter: {
18
- regex: '^(__dirname|__filename)$',
19
- match: false
20
- }
21
- },
22
- // Allow camelCase functions (23.2), and PascalCase functions (23.8)
23
- {
24
- selector: 'function',
25
- format: ['camelCase', 'PascalCase']
26
- },
27
- // Airbnb recommends PascalCase for classes (23.3),
28
- // and although Airbnb does not make TypeScript recommendations,
29
- // we are assuming this rule would similarly apply to anything "type like",
30
- // including interfaces, type aliases, and enums
31
- {
32
- selector: 'typeLike',
33
- format: ['PascalCase']
34
- },
35
- {
36
- selector: 'parameter',
37
- format: ['camelCase'],
38
- leadingUnderscore: 'allow'
39
- },
40
- {
41
- selector: 'method',
42
- format: ['camelCase', 'PascalCase']
43
- },
44
- {
45
- selector: 'typeProperty',
46
- format: ['camelCase']
47
- },
48
- {
49
- selector: 'enumMember',
50
- format: ['PascalCase', 'UPPER_CASE']
51
- }
52
- ],
53
- // 禁止没有必要的初始化
54
- '@typescript-eslint/no-inferrable-types': 'error',
55
- // 函数中未使用await,函数签名不要加async
56
- '@typescript-eslint/require-await': 'error',
57
- // 没有必要的类型as
58
- '@typescript-eslint/no-unnecessary-type-assertion': 'error',
59
- // 数组用T[]而不是Array<T>
60
- '@typescript-eslint/array-type': ['error', { default: 'array' }],
61
- // Promise必须加await或void
62
- '@typescript-eslint/no-misused-promises': [
63
- 'error',
64
- {
65
- checksVoidReturn: false
66
- }
67
- ],
68
- // 以下是关闭的规则
69
- '@typescript-eslint/strict-boolean-expressions': 'off',
70
- '@typescript-eslint/explicit-function-return-type': 'off',
71
- '@typescript-eslint/restrict-template-expressions': 'off',
72
- '@typescript-eslint/no-non-null-assertion': 'off',
73
- '@typescript-eslint/method-signature-style': 'off',
74
- '@typescript-eslint/consistent-type-assertions': 'off',
75
- '@typescript-eslint/no-extraneous-class': 'off',
76
- '@typescript-eslint/no-confusing-void-expression': 'off',
77
- '@typescript-eslint/explicit-member-accessibility': 'off',
78
- '@typescript-eslint/unbound-method': 'off',
79
- '@typescript-eslint/no-unsafe-argument': 'off'
80
- }
81
- };
@@ -1,35 +0,0 @@
1
- module.exports = {
2
- plugins: ['unicorn'],
3
- extends: ['plugin:unicorn/recommended'],
4
- rules: {
5
- // unicorn默认规则太严格,屏蔽以下
6
- 'unicorn/filename-case': 'off',
7
- 'unicorn/import-style': 'off',
8
- 'unicorn/prefer-at': 'off',
9
- 'unicorn/prevent-abbreviations': 'off',
10
- 'unicorn/prefer-date-now': 'off',
11
- 'unicorn/no-process-exit': 'off',
12
- 'unicorn/prefer-module': 'off',
13
- 'unicorn/no-null': 'off',
14
- 'unicorn/prefer-top-level-await': 'off',
15
- 'unicorn/consistent-function-scoping': 'off',
16
- 'unicorn/numeric-separators-style': 'off',
17
- 'unicorn/prefer-optional-catch-binding': 'off',
18
- 'unicorn/no-negated-condition': 'off',
19
- 'unicorn/switch-case-braces': 'off',
20
- 'unicorn/no-array-for-each': 'off',
21
- 'unicorn/prefer-ternary': 'off',
22
- 'unicorn/better-regex': 'off',
23
- 'unicorn/error-message': 'off',
24
- 'unicorn/no-object-as-default-parameter': 'off',
25
- 'unicorn/no-array-push-push': 'off',
26
- 'unicorn/no-useless-undefined': 'off',
27
- 'unicorn/prefer-blob-reading-methods': 'off',
28
- 'unicorn/catch-error-name': [
29
- 'error',
30
- {
31
- name: 'err'
32
- }
33
- ]
34
- }
35
- };
package/lib/index.js DELETED
@@ -1,56 +0,0 @@
1
- module.exports = {
2
- overrides: [
3
- {
4
- files: [
5
- '*.ts',
6
- '*.tsx',
7
- '*.cts',
8
- '*.mts',
9
- '*.js',
10
- '*.jsx',
11
- '*.cjs',
12
- '*.mjs'
13
- ],
14
- parser: '@typescript-eslint/parser',
15
- extends: [
16
- './configs/env',
17
- './configs/standard',
18
- './configs/ts',
19
- './configs/promise',
20
- './configs/import',
21
- './configs/unicorn',
22
- './configs/react',
23
- './configs/jsdoc',
24
- './configs/lodash',
25
- './configs/eslint',
26
- './configs/deprecation',
27
- './configs/cspell',
28
- './configs/agilebot',
29
- './configs/prettier'
30
- ]
31
- },
32
- {
33
- files: ['*.ts', '*.tsx'],
34
- rules: {
35
- '@typescript-eslint/explicit-member-accessibility': 'error'
36
- }
37
- },
38
- {
39
- files: ['*.d.ts'],
40
- rules: {
41
- // .d.ts中支持导入ts文件中的类型
42
- '@typescript-eslint/consistent-type-imports': 'off',
43
- // .d.ts中忽略属性命名规则
44
- '@typescript-eslint/naming-convention': 'off',
45
- // .d.ts中忽略三斜线引用
46
- '@typescript-eslint/triple-slash-reference': 'off'
47
- }
48
- },
49
- {
50
- files: ['*.js', '*.jsx', '*.cjs'],
51
- rules: {
52
- '@typescript-eslint/no-var-requires': 'off'
53
- }
54
- }
55
- ]
56
- };