@huangjunsen/eslint-config 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -253,8 +253,9 @@ describe('Validate TS configs', () => {
253
253
  assert.strictEqual(ruleIds.includes('no-console'), true);
254
254
  assert.strictEqual(ruleIds.includes('no-var'), true);
255
255
  assert.strictEqual(ruleIds.includes('eol-last'), true);
256
- assert.equal(errorCount, 2);
257
- assert.equal(warningCount, 3);
256
+ // 不硬编码具体数量,避免插件升级引起规则集变化时测试失效
257
+ assert.ok(errorCount > 0, `期望存在 error 级别问题,实际为 ${errorCount}`);
258
+ assert.ok(warningCount > 0, `期望存在 warning 级别问题,实际为 ${warningCount}`);
258
259
 
259
260
  // 验证已关闭的 link 规则是否校验正常,以 @typescript-eslint/explicit-function-return-type 为例
260
261
  assert.strictEqual(ruleIds.includes('@typescript-eslint/explicit-function-return-type'), false);
@@ -1,15 +1,5 @@
1
1
  module.exports = {
2
2
  rules: {
3
- // 使用 2 个空格缩进
4
- // @unessential
5
- '@typescript-eslint/indent': 'off',
6
-
7
- // 使用分号
8
- // @unessential
9
- '@typescript-eslint/semi': 'off',
10
-
11
3
  '@typescript-eslint/adjacent-overload-signatures': 'warn',
12
-
13
- '@typescript-eslint/no-parameter-properties': 'warn',
14
4
  },
15
5
  };
package/flat/index.js CHANGED
@@ -1,10 +1,15 @@
1
1
  const globals = require('globals');
2
+ const { prettierOverrides } = require('./shared');
2
3
 
3
4
  /**
4
- * 基础 JS Flat Config 配置
5
+ * 基础 Flat Config(JavaScript)
6
+ *
7
+ * 只包含语言选项与通用的逻辑防错规则,不含格式化规则,
8
+ * 格式化统一交给 Prettier 完成。
5
9
  */
6
10
  module.exports = [
7
11
  {
12
+ name: 'fe-spec/base/language-options',
8
13
  languageOptions: {
9
14
  ecmaVersion: 'latest',
10
15
  sourceType: 'module',
@@ -17,8 +22,10 @@ module.exports = [
17
22
  linterOptions: {
18
23
  reportUnusedDisableDirectives: 'warn',
19
24
  },
25
+ },
26
+ {
27
+ name: 'fe-spec/base/rules',
20
28
  rules: {
21
- // 常见逻辑防错规则(非纯排版格式)
22
29
  'no-var': 'error',
23
30
  'prefer-const': ['error', { destructuring: 'all' }],
24
31
  'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
@@ -29,4 +36,5 @@ module.exports = [
29
36
  eqeqeq: ['warn', 'always', { null: 'ignore' }],
30
37
  },
31
38
  },
39
+ ...prettierOverrides(),
32
40
  ];
package/flat/node.js ADDED
@@ -0,0 +1,18 @@
1
+ const globals = require('globals');
2
+ const { prettierOverrides } = require('./shared');
3
+
4
+ /**
5
+ * Node.js Flat Config 配置
6
+ */
7
+ module.exports = [
8
+ ...require('./index'),
9
+ {
10
+ name: 'fe-spec/node/language-options',
11
+ languageOptions: {
12
+ globals: {
13
+ ...globals.node,
14
+ },
15
+ },
16
+ },
17
+ ...prettierOverrides(),
18
+ ];
package/flat/react.js CHANGED
@@ -1,19 +1,47 @@
1
- const base = require('./index');
1
+ const react = require('eslint-plugin-react');
2
+ const reactHooks = require('eslint-plugin-react-hooks');
3
+ const jsxA11y = require('eslint-plugin-jsx-a11y');
4
+ const tsParser = require('@typescript-eslint/parser');
5
+ const { prettierOverrides } = require('./shared');
2
6
 
3
7
  /**
4
8
  * React Flat Config 配置
5
9
  */
6
10
  module.exports = [
7
- ...base,
11
+ ...require('./index'),
8
12
  {
9
- files: ['**/*.jsx', '**/*.tsx'],
13
+ name: 'fe-spec/react/setup',
14
+ files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
10
15
  languageOptions: {
11
16
  parserOptions: {
12
- ecmaFeatures: {
13
- jsx: true,
14
- },
17
+ ecmaFeatures: { jsx: true },
18
+ },
19
+ },
20
+ plugins: {
21
+ react,
22
+ 'react-hooks': reactHooks,
23
+ 'jsx-a11y': jsxA11y,
24
+ },
25
+ settings: {
26
+ react: { version: 'detect' },
27
+ },
28
+ rules: {
29
+ ...react.configs.recommended.rules,
30
+ ...reactHooks.configs.recommended.rules,
31
+ ...jsxA11y.configs.recommended.rules,
32
+ },
33
+ },
34
+ {
35
+ name: 'fe-spec/react/typescript',
36
+ files: ['**/*.tsx'],
37
+ languageOptions: {
38
+ parser: tsParser,
39
+ parserOptions: {
40
+ ecmaVersion: 'latest',
41
+ sourceType: 'module',
42
+ ecmaFeatures: { jsx: true },
15
43
  },
16
44
  },
17
- rules: {},
18
45
  },
46
+ ...prettierOverrides(),
19
47
  ];
package/flat/shared.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 共享依赖加载器(Flat Config 内部使用)
3
+ *
4
+ * 统一在此处加载 TypeScript / Prettier 相关依赖,保证各 flat 预设行为一致。
5
+ */
6
+
7
+ /**
8
+ * 统一转成数组,兼容插件导出的 flat 配置可能为对象或数组
9
+ */
10
+ function toArray(config) {
11
+ if (!config) return [];
12
+ return Array.isArray(config) ? config : [config];
13
+ }
14
+
15
+ /**
16
+ * 关闭所有与 Prettier 冲突的格式化规则
17
+ */
18
+ function prettierOverrides() {
19
+ try {
20
+ return toArray(require('eslint-config-prettier/flat'));
21
+ } catch (e) {
22
+ try {
23
+ return toArray(require('eslint-config-prettier'));
24
+ } catch (err) {
25
+ return [];
26
+ }
27
+ }
28
+ }
29
+
30
+ module.exports = { toArray, prettierOverrides };
@@ -1,15 +1,55 @@
1
- const base = require('./index');
1
+ const tseslint = require('typescript-eslint');
2
+ const tsPlugin = require('@typescript-eslint/eslint-plugin');
3
+ const { toArray, prettierOverrides } = require('./shared');
4
+
5
+ /**
6
+ * TypeScript 文件
7
+ */
8
+ const tsFiles = ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'];
2
9
 
3
10
  /**
4
11
  * TypeScript Flat Config 配置
12
+ *
13
+ * - ts/tsx 文件使用 @typescript-eslint/parser
14
+ * - 规则同时作用于 .vue(单文件组件中的 <script lang="ts"> 由 vue-eslint-parser 调用 TS parser 解析)
5
15
  */
6
16
  module.exports = [
7
- ...base,
17
+ ...require('./index'),
18
+ ...toArray(tseslint.configs.recommended).map((config) => ({
19
+ ...config,
20
+ files: config.files || tsFiles,
21
+ })),
22
+ {
23
+ name: 'fe-spec/typescript/vue-plugin',
24
+ files: ['**/*.vue'],
25
+ plugins: {
26
+ '@typescript-eslint': tsPlugin,
27
+ },
28
+ },
29
+ {
30
+ name: 'fe-spec/typescript/tsx',
31
+ files: ['**/*.tsx'],
32
+ languageOptions: {
33
+ parserOptions: {
34
+ ecmaFeatures: {
35
+ jsx: true,
36
+ },
37
+ },
38
+ },
39
+ },
8
40
  {
9
- files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],
41
+ name: 'fe-spec/typescript/rules',
42
+ files: [...tsFiles, '**/*.vue'],
10
43
  rules: {
44
+ // TS 由编译器与 @typescript-eslint 检查,关闭 ESLint 原生规则避免误报
11
45
  'no-unused-vars': 'off',
12
- // TS 规范
46
+ 'no-undef': 'off',
47
+ '@typescript-eslint/no-explicit-any': 'warn',
48
+ '@typescript-eslint/no-unused-vars': [
49
+ 'warn',
50
+ { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
51
+ ],
13
52
  },
14
53
  },
54
+ ...prettierOverrides(),
15
55
  ];
package/flat/vue.js CHANGED
@@ -1,12 +1,39 @@
1
- const base = require('./index');
1
+ const vue = require('eslint-plugin-vue');
2
+ const vueParser = require('vue-eslint-parser');
3
+ const tsParser = require('@typescript-eslint/parser');
4
+ const { toArray, prettierOverrides } = require('./shared');
2
5
 
3
6
  /**
4
7
  * Vue Flat Config 配置
8
+ *
9
+ * - 使用 eslint-plugin-vue 官方的 flat/recommended 规则集
10
+ * - <script> 按 lang 自动选择子解析器,因此 JS / TS 项目均可直接使用
5
11
  */
6
12
  module.exports = [
7
- ...base,
13
+ ...require('./index'),
14
+ ...toArray(vue.configs['flat/recommended']),
8
15
  {
16
+ name: 'fe-spec/vue/parser',
9
17
  files: ['**/*.vue'],
10
- rules: {},
18
+ languageOptions: {
19
+ parser: vueParser,
20
+ parserOptions: {
21
+ ecmaVersion: 'latest',
22
+ sourceType: 'module',
23
+ // 支持 <script lang="tsx"> 中的 JSX 写法
24
+ ecmaFeatures: {
25
+ jsx: true,
26
+ },
27
+ // https://github.com/vuejs/vue-eslint-parser#parseroptionsparser
28
+ parser: {
29
+ js: 'espree',
30
+ jsx: 'espree',
31
+ ts: tsParser,
32
+ tsx: tsParser,
33
+ },
34
+ extraFileExtensions: ['.vue'],
35
+ },
36
+ },
11
37
  },
38
+ ...prettierOverrides(),
12
39
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huangjunsen/eslint-config",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "main": "index.js",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -8,6 +8,7 @@
8
8
  "./flat/typescript": "./flat/typescript.js",
9
9
  "./flat/react": "./flat/react.js",
10
10
  "./flat/vue": "./flat/vue.js",
11
+ "./flat/node": "./flat/node.js",
11
12
  "./vue": "./vue.js",
12
13
  "./react": "./react.js",
13
14
  "./node": "./node.js",
@@ -36,27 +37,29 @@
36
37
  "url": "https://github.com/Huang-junsen/js-encode-fe-spec/issues"
37
38
  },
38
39
  "dependencies": {
39
- "globals": "^15.0.0"
40
- },
41
- "devDependencies": {
42
40
  "@babel/core": "^7.24.4",
43
41
  "@babel/eslint-parser": "^7.24.1",
44
42
  "@babel/preset-react": "^7.24.1",
45
- "@typescript-eslint/eslint-plugin": "^7.7.0",
46
- "@typescript-eslint/parser": "^7.7.0",
47
- "eslint": "^8.7.0",
43
+ "@typescript-eslint/eslint-plugin": "^8.70.0",
44
+ "@typescript-eslint/parser": "^8.70.0",
48
45
  "eslint-config-egg": "^13.1.0",
46
+ "eslint-config-prettier": "^10.1.8",
49
47
  "eslint-import-resolver-typescript": "^3.6.1",
50
48
  "eslint-plugin-import": "^2.29.1",
51
49
  "eslint-plugin-jsx-a11y": "^6.8.0",
52
50
  "eslint-plugin-jsx-plus": "^0.1.0",
53
51
  "eslint-plugin-react": "^7.34.1",
54
52
  "eslint-plugin-react-hooks": "^4.6.0",
55
- "eslint-plugin-vue": "^9.25.0",
53
+ "eslint-plugin-vue": "^10.11.0",
54
+ "globals": "^15.0.0",
56
55
  "lodash": "^4.17.21",
56
+ "typescript-eslint": "^8.70.0",
57
+ "vue-eslint-parser": "^10.4.1"
58
+ },
59
+ "devDependencies": {
60
+ "eslint": "^8.7.0",
57
61
  "mocha": "^10.4.0",
58
- "typescript": "5.0.4",
59
- "vue-eslint-parser": "^9.4.2"
62
+ "typescript": "5.0.4"
60
63
  },
61
64
  "scripts": {
62
65
  "lint": "eslint ./",
@@ -64,41 +64,12 @@ module.exports = {
64
64
  */
65
65
  '@typescript-eslint/ban-tslint-comment': 'error',
66
66
 
67
- /**
68
- * 【关闭】禁止使用指定的类型
69
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/ban-types.md
70
- */
71
- '@typescript-eslint/ban-types': 'off',
72
-
73
- /**
74
- * 【强制】大括号换行风格:one true brace style 风格,且单行代码块可不换行
75
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/brace-style.md
76
- * @extend
77
- */
78
- 'brace-style': 'off',
79
- '@typescript-eslint/brace-style': [
80
- 'error',
81
- '1tbs',
82
- { allowSingleLine: true },
83
- ],
84
-
85
67
  /**
86
68
  * 【推荐】类的属性如果是字面量,则必须是只读属性而不能用 getter
87
69
  * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/class-literal-property-style.md
88
70
  */
89
71
  '@typescript-eslint/class-literal-property-style': ['warn', 'fields'],
90
72
 
91
- /**
92
- * 【强制】逗号的前面无空格,后面有空格
93
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/comma-spacing.md
94
- * @extend
95
- */
96
- 'comma-spacing': 'off',
97
- '@typescript-eslint/comma-spacing': [
98
- 'error',
99
- { before: false, after: true },
100
- ],
101
-
102
73
  /**
103
74
  * 【强制】类型断言必须使用 as Type 而非 <T>,对象字面量禁止类型断言(断言成 any 除外)
104
75
  * <T> 容易与 JSX 语法混淆
@@ -154,61 +125,6 @@ module.exports = {
154
125
  */
155
126
  '@typescript-eslint/explicit-module-boundary-types': 'off',
156
127
 
157
- /**
158
- * 【强制】函数名与调用它的括号间无空格
159
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/func-call-spacing.md
160
- */
161
- 'func-call-spacing': 'off',
162
- '@typescript-eslint/func-call-spacing': ['error', 'never'],
163
-
164
- /**
165
- * 【强制】缩进为两个空格
166
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/indent.md
167
- */
168
- indent: 'off',
169
- '@typescript-eslint/indent': [
170
- 'error',
171
- 2,
172
- {
173
- SwitchCase: 1,
174
- VariableDeclarator: 1,
175
- outerIIFEBody: 1,
176
- // MemberExpression: null,
177
- FunctionDeclaration: {
178
- parameters: 1,
179
- body: 1,
180
- },
181
- FunctionExpression: {
182
- parameters: 1,
183
- body: 1,
184
- },
185
- CallExpression: {
186
- arguments: 1,
187
- },
188
- ArrayExpression: 1,
189
- ObjectExpression: 1,
190
- ImportDeclaration: 1,
191
- flatTernaryExpressions: false,
192
- // list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js
193
- ignoredNodes: [
194
- 'JSXElement',
195
- 'JSXElement > *',
196
- 'JSXAttribute',
197
- 'JSXIdentifier',
198
- 'JSXNamespacedName',
199
- 'JSXMemberExpression',
200
- 'JSXSpreadAttribute',
201
- 'JSXExpressionContainer',
202
- 'JSXOpeningElement',
203
- 'JSXClosingElement',
204
- 'JSXText',
205
- 'JSXEmptyExpression',
206
- 'JSXSpreadChild',
207
- ],
208
- ignoreComments: false,
209
- },
210
- ],
211
-
212
128
  /**
213
129
  * 【关闭】变量必须在定义的时候赋值
214
130
  * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/init-declarations.md
@@ -217,39 +133,6 @@ module.exports = {
217
133
  'init-declarations': 'off',
218
134
  '@typescript-eslint/init-declarations': 'off',
219
135
 
220
- /**
221
- * 【强制】关键字前后有一个空格
222
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/keyword-spacing.md
223
- * @extend
224
- */
225
- 'keyword-spacing': 'off',
226
- '@typescript-eslint/keyword-spacing': [
227
- 'error',
228
- {
229
- before: true,
230
- after: true,
231
- overrides: {
232
- return: { after: true },
233
- throw: { after: true },
234
- case: { after: true },
235
- },
236
- },
237
- ],
238
-
239
- /**
240
- * 【关闭】类成员之间保留一个空行
241
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/lines-between-class-members.md
242
- * @extend
243
- */
244
- 'lines-between-class-members': 'off',
245
- '@typescript-eslint/lines-between-class-members': 'off',
246
-
247
- /**
248
- * 【强制】interface/type 类型中保持一致的成员分隔符分号「;」,单行类型的最后一个元素不加分号
249
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/member-delimiter-style.md
250
- */
251
- '@typescript-eslint/member-delimiter-style': 'error',
252
-
253
136
  /**
254
137
  * 【推荐】类成员的遵循一定的排序规则
255
138
  * 1. 类的静态方法/属性(static)优先于实例的方法/属性(instance)
@@ -303,8 +186,6 @@ module.exports = {
303
186
  * 【关闭】限制各种变量或类型的命名规则
304
187
  * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/naming-convention.md
305
188
  */
306
- camelcase: 'off',
307
- '@typescript-eslint/camelcase': 'off',
308
189
  '@typescript-eslint/naming-convention': 'off',
309
190
 
310
191
  /**
@@ -372,21 +253,6 @@ module.exports = {
372
253
  */
373
254
  '@typescript-eslint/no-extra-non-null-assertion': 'off',
374
255
 
375
- /**
376
- * 【关闭】禁止不必要的小括号
377
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-extra-parens.md
378
- */
379
- 'no-extra-parens': 'off',
380
- '@typescript-eslint/no-extra-parens': 'off',
381
-
382
- /**
383
- * 【强制】禁止不必要的分号
384
- * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-extra-semi.md
385
- * @extend
386
- */
387
- 'no-extra-semi': 'off',
388
- '@typescript-eslint/no-extra-semi': 'error',
389
-
390
256
  /**
391
257
  * 【关闭】禁止定义没必要的类,比如只有静态方法的类
392
258
  * @link https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-extraneous-class.md
@@ -472,11 +338,6 @@ module.exports = {
472
338
  */
473
339
  '@typescript-eslint/no-non-null-assertion': 'off',
474
340
 
475
- /**
476
- * 【关闭】禁止给类的构造函数的参数添加修饰符
477
- */
478
- '@typescript-eslint/no-parameter-properties': 'off',
479
-
480
341
  /**
481
342
  * 【推荐】不建议使用 require 引入模块,使用 import
482
343
  */
@@ -499,16 +360,6 @@ module.exports = {
499
360
  },
500
361
  ],
501
362
 
502
- /**
503
- * 【关闭】禁止 throw 字面量,必须 throw 一个 Error 对象
504
- */
505
- '@typescript-eslint/no-throw-literal': 'off',
506
-
507
- /**
508
- * 【关闭】禁止使用类型别名
509
- */
510
- '@typescript-eslint/no-type-alias': 'off',
511
-
512
363
  /**
513
364
  * 【关闭】测试表达式中的布尔类型禁止与 true 或 false 直接比较
514
365
  */
@@ -578,11 +429,6 @@ module.exports = {
578
429
  { vars: 'all', args: 'after-used', ignoreRestSiblings: true },
579
430
  ],
580
431
 
581
- /**
582
- * 【关闭】禁止已定义的变量未使用
583
- */
584
- '@typescript-eslint/no-unused-vars-experimental': 'off',
585
-
586
432
  /**
587
433
  * 【强制】禁止在定义变量之前就使用它
588
434
  * @extend
@@ -676,12 +522,6 @@ module.exports = {
676
522
  */
677
523
  '@typescript-eslint/promise-function-async': 'off',
678
524
 
679
- /**
680
- * 【强制】ts 文件字符串字面量优先使用单引号
681
- */
682
- quotes: 'off',
683
- '@typescript-eslint/quotes': ['error', 'single', { avoidEscape: true }],
684
-
685
525
  /**
686
526
  * 【关闭】async 函数中必须存在 await 语句
687
527
  */
@@ -705,27 +545,6 @@ module.exports = {
705
545
  'no-return-await': 'off',
706
546
  '@typescript-eslint/return-await': 'off',
707
547
 
708
- /**
709
- * 【强制】添加分号
710
- * @extend
711
- */
712
- semi: 'off',
713
- '@typescript-eslint/semi': ['error', 'always'],
714
-
715
- /**
716
- * 【强制】命名函数的空格规则,遵循 JS 约定
717
- * @extend
718
- */
719
- 'space-before-function-paren': 'off',
720
- '@typescript-eslint/space-before-function-paren': [
721
- 'error',
722
- {
723
- anonymous: 'always',
724
- named: 'never',
725
- asyncArrow: 'always',
726
- },
727
- ],
728
-
729
548
  /**
730
549
  * 【关闭】条件判断必须传入布尔值
731
550
  */
@@ -748,11 +567,6 @@ module.exports = {
748
567
  },
749
568
  ],
750
569
 
751
- /**
752
- * 【强制】定义类型时应正确添加空格
753
- */
754
- '@typescript-eslint/type-annotation-spacing': 'error',
755
-
756
570
  /**
757
571
  * 【强制】interface 和 type 定义时必须声明成员的类型
758
572
  */