@zjutjh/eslint-config 0.4.1 → 0.5.2
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/README.md +42 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +176 -40
- package/package.json +11 -5
package/README.md
CHANGED
|
@@ -78,6 +78,48 @@ export default [
|
|
|
78
78
|
$ npm run lint
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
## 代码格式化
|
|
82
|
+
|
|
83
|
+
很多人在意代码的格式化,这里单独拿出一章讲。
|
|
84
|
+
|
|
85
|
+
支持使用 `@stylistic/eslint-plugin` (lint 工具对格式的检查) 或者传统的 formatter 工具
|
|
86
|
+
(Prettier) 来对代码进行格式化。具体配置放在 `options.codeStyle` 下面。codeStyle 默认开启,以
|
|
87
|
+
`@stylistic/eslint-plugin` 做为默认的风格规范工具。如果要使用 formatter,需要手动开启。
|
|
88
|
+
|
|
89
|
+
> [!IMPORTANT]
|
|
90
|
+
> stylistic 和 formatter 在配置上互斥,选择其中之一即可,我们会保证两者在大部分场景下代码风格的一致性。一般来说,formatter 对格式的要求比 stylistic 更严格。
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
// 启用 formatter,可选传入 prettier 的相关配置
|
|
94
|
+
export default [
|
|
95
|
+
...(await zjutjh({
|
|
96
|
+
codeStyle: {
|
|
97
|
+
tool: "formatter"
|
|
98
|
+
prettier: {}
|
|
99
|
+
}
|
|
100
|
+
})),
|
|
101
|
+
];
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
stylistic 只对 js(x) 和 ts(x) 进行格式化,而 formatter 还对其他文件,如 css,vue template 等配置了格式化。
|
|
105
|
+
如果你要格式化这些文件,需要配置编辑器来允许 eslint 校验这些类型的文件。
|
|
106
|
+
|
|
107
|
+
```jsonc
|
|
108
|
+
// 可以参考仓库下的 .vscode/settings.json 给 vscode 配置
|
|
109
|
+
// @filename .vscode/settings.json
|
|
110
|
+
{
|
|
111
|
+
"prettier.enable": false, // 如果安装了 prettier 插件,需要在项目中关闭
|
|
112
|
+
"[scss]": {
|
|
113
|
+
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
|
114
|
+
},
|
|
115
|
+
"eslint.validate": [
|
|
116
|
+
"scss"
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
> [!WARNING]
|
|
121
|
+
> 我们使用 eslint 调用 prettier 可执行文件来进行代码格式化,所以你的编辑器不需要安装 prettier 插件,有 eslint 插件就行。prettier 的格式化配置声明在配置源码内部,如果启用了 prettier 插件,他读取不到内部的配置,会按照默认的配置来格式化,这会导致代码风格不一致。
|
|
122
|
+
|
|
81
123
|
## 开发指南
|
|
82
124
|
|
|
83
125
|
推荐使用官方的 [@eslint/config-inspector](https://github.com/eslint/config-inspector) 来可视化调试配置。
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ type OptionsConfig = {
|
|
|
10
10
|
vue?: boolean;
|
|
11
11
|
ts?: boolean | (OptionsOverrides & OptionsTypeScriptParserOptions);
|
|
12
12
|
taro?: boolean;
|
|
13
|
+
codeStyle?: boolean | OptionsCodeStyle<string>;
|
|
13
14
|
overrides?: OverridesConfigs;
|
|
14
15
|
};
|
|
15
16
|
type OptionsOverrides = {
|
|
@@ -18,6 +19,21 @@ type OptionsOverrides = {
|
|
|
18
19
|
interface OptionsTypeScriptParserOptions {
|
|
19
20
|
parserOptions?: Partial<ParserOptions>;
|
|
20
21
|
}
|
|
22
|
+
type OptionsStylistic = {
|
|
23
|
+
tool: "stylistic";
|
|
24
|
+
};
|
|
25
|
+
type OptionsFormatter = {
|
|
26
|
+
tool: "formatter";
|
|
27
|
+
/**
|
|
28
|
+
* 自定义 prettier 配置
|
|
29
|
+
* @see https://prettier.io/docs/options
|
|
30
|
+
*/
|
|
31
|
+
prettier?: Record<string, any>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* 默认使用 `@stylistic/eslint-plugin` 作为 formatter
|
|
35
|
+
*/
|
|
36
|
+
type OptionsCodeStyle<T extends string> = T extends OptionsStylistic["tool"] ? OptionsStylistic : OptionsFormatter;
|
|
21
37
|
|
|
22
38
|
declare function zjutjh(options?: OptionsConfig): Promise<Linter.Config<Linter.RulesRecord>[]>;
|
|
23
39
|
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,147 @@
|
|
|
1
1
|
// src/factory.ts
|
|
2
2
|
import { isPackageExists as isPackageExists2 } from "local-pkg";
|
|
3
3
|
|
|
4
|
+
// src/utils.ts
|
|
5
|
+
import { isPackageExists } from "local-pkg";
|
|
6
|
+
async function interopDefault(m) {
|
|
7
|
+
const resolved = await m;
|
|
8
|
+
return resolved.default || resolved;
|
|
9
|
+
}
|
|
10
|
+
async function ensurePackages(packages) {
|
|
11
|
+
const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
|
|
12
|
+
if (nonExistingPackages.length !== 0) {
|
|
13
|
+
const message = `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}.`;
|
|
14
|
+
throw new Error(message);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function resolveSubOptions(options, key) {
|
|
18
|
+
if (typeof options[key] === "boolean") {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
return options[key] || {};
|
|
22
|
+
}
|
|
23
|
+
function getOverrides(options, key) {
|
|
24
|
+
return {
|
|
25
|
+
...options.overrides?.[key]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/configs/formatter.ts
|
|
30
|
+
var prettierOptions = {
|
|
31
|
+
printWidth: 100,
|
|
32
|
+
tabWidth: 2,
|
|
33
|
+
useTabs: false,
|
|
34
|
+
semi: true,
|
|
35
|
+
singleQuote: false,
|
|
36
|
+
quoteProps: "as-needed",
|
|
37
|
+
jsxSingleQuote: false,
|
|
38
|
+
trailingComma: "none",
|
|
39
|
+
bracketSpacing: true,
|
|
40
|
+
bracketSameLine: false,
|
|
41
|
+
arrowParens: "always",
|
|
42
|
+
requirePragma: false,
|
|
43
|
+
insertPragma: false,
|
|
44
|
+
proseWrap: "preserve",
|
|
45
|
+
htmlWhitespaceSensitivity: "css",
|
|
46
|
+
vueIndentScriptAndStyle: false,
|
|
47
|
+
endOfLine: "lf",
|
|
48
|
+
embeddedLanguageFormatting: "auto",
|
|
49
|
+
singleAttributePerLine: false
|
|
50
|
+
};
|
|
51
|
+
async function formatter(options) {
|
|
52
|
+
await ensurePackages([
|
|
53
|
+
"eslint-plugin-format"
|
|
54
|
+
]);
|
|
55
|
+
const [
|
|
56
|
+
pluginFormat
|
|
57
|
+
] = await Promise.all([
|
|
58
|
+
interopDefault(import("eslint-plugin-format"))
|
|
59
|
+
]);
|
|
60
|
+
const mergedPrettierOptions = {
|
|
61
|
+
...prettierOptions,
|
|
62
|
+
...options?.prettier
|
|
63
|
+
};
|
|
64
|
+
return [
|
|
65
|
+
{
|
|
66
|
+
name: "zjutjh/formatter/setup",
|
|
67
|
+
plugins: {
|
|
68
|
+
format: pluginFormat
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "zjutjh/formatter/css/rules",
|
|
73
|
+
languageOptions: {
|
|
74
|
+
parser: pluginFormat.parserPlain
|
|
75
|
+
},
|
|
76
|
+
files: [
|
|
77
|
+
"**/*.less",
|
|
78
|
+
"**/*.css",
|
|
79
|
+
"**/*.scss",
|
|
80
|
+
"**/*.sass"
|
|
81
|
+
],
|
|
82
|
+
rules: {
|
|
83
|
+
"format/prettier": ["error", { parser: "css", ...mergedPrettierOptions }]
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "zjutjh/formatter/vue/rules",
|
|
88
|
+
languageOptions: {
|
|
89
|
+
parser: pluginFormat.parserPlain
|
|
90
|
+
},
|
|
91
|
+
files: [
|
|
92
|
+
"**/*.vue"
|
|
93
|
+
],
|
|
94
|
+
rules: {
|
|
95
|
+
"format/prettier": ["error", { parser: "vue", ...mergedPrettierOptions }]
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "zjutjh/formatter/json/rules",
|
|
100
|
+
languageOptions: {
|
|
101
|
+
parser: pluginFormat.parserPlain
|
|
102
|
+
},
|
|
103
|
+
files: [
|
|
104
|
+
"**/*.json"
|
|
105
|
+
],
|
|
106
|
+
rules: {
|
|
107
|
+
"format/prettier": ["error", { parser: "json", ...mergedPrettierOptions }]
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "zjutjh/formatter/html/rules",
|
|
112
|
+
languageOptions: {
|
|
113
|
+
parser: pluginFormat.parserPlain
|
|
114
|
+
},
|
|
115
|
+
files: [
|
|
116
|
+
"**/*.html"
|
|
117
|
+
],
|
|
118
|
+
rules: {
|
|
119
|
+
"format/prettier": ["error", { parser: "html", ...mergedPrettierOptions }]
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "zjutjh/formatter/js/rules",
|
|
124
|
+
languageOptions: {
|
|
125
|
+
parser: pluginFormat.parserPlain
|
|
126
|
+
},
|
|
127
|
+
files: ["**/*.js", "**/*.jsx"],
|
|
128
|
+
rules: {
|
|
129
|
+
"format/prettier": ["error", { parser: "babel", ...mergedPrettierOptions }]
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "zjutjh/formatter/ts/rules",
|
|
134
|
+
languageOptions: {
|
|
135
|
+
parser: pluginFormat.parserPlain
|
|
136
|
+
},
|
|
137
|
+
files: ["**/*.ts", "**/*.tsx"],
|
|
138
|
+
rules: {
|
|
139
|
+
"format/prettier": ["error", { parser: "typescript", ...mergedPrettierOptions }]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
|
|
4
145
|
// src/configs/imports.ts
|
|
5
146
|
import simpleImportSortPlugin from "eslint-plugin-simple-import-sort";
|
|
6
147
|
function imports() {
|
|
@@ -57,10 +198,15 @@ function javascript() {
|
|
|
57
198
|
...eslintJS.configs.recommended.rules,
|
|
58
199
|
"camelcase": "warn",
|
|
59
200
|
"no-warning-comments": "warn",
|
|
60
|
-
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
201
|
+
"no-console": ["warn", { allow: ["warn", "error", "info"] }],
|
|
61
202
|
"no-var": "error",
|
|
62
203
|
"no-undef": "off",
|
|
63
|
-
"prefer-const": "warn"
|
|
204
|
+
"prefer-const": "warn",
|
|
205
|
+
"arrow-body-style": "error",
|
|
206
|
+
"no-nested-ternary": "error",
|
|
207
|
+
"curly": "error",
|
|
208
|
+
"no-else-return": "error",
|
|
209
|
+
"no-implicit-coercion": "error"
|
|
64
210
|
}
|
|
65
211
|
}
|
|
66
212
|
];
|
|
@@ -109,31 +255,6 @@ function stylistic(options) {
|
|
|
109
255
|
];
|
|
110
256
|
}
|
|
111
257
|
|
|
112
|
-
// src/utils.ts
|
|
113
|
-
import { isPackageExists } from "local-pkg";
|
|
114
|
-
async function interopDefault(m) {
|
|
115
|
-
const resolved = await m;
|
|
116
|
-
return resolved.default || resolved;
|
|
117
|
-
}
|
|
118
|
-
async function ensurePackages(packages) {
|
|
119
|
-
const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
|
|
120
|
-
if (nonExistingPackages.length !== 0) {
|
|
121
|
-
const message = `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}.`;
|
|
122
|
-
throw new Error(message);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
function resolveSubOptions(options, key) {
|
|
126
|
-
if (typeof options[key] === "boolean") {
|
|
127
|
-
return {};
|
|
128
|
-
}
|
|
129
|
-
return options[key] || {};
|
|
130
|
-
}
|
|
131
|
-
function getOverrides(options, key) {
|
|
132
|
-
return {
|
|
133
|
-
...options.overrides?.[key]
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
258
|
// src/configs/typescript.ts
|
|
138
259
|
async function typescript(options) {
|
|
139
260
|
const {
|
|
@@ -155,6 +276,7 @@ async function typescript(options) {
|
|
|
155
276
|
{
|
|
156
277
|
name: "zjutjh/typescript/setup",
|
|
157
278
|
plugins: {
|
|
279
|
+
// @ts-expect-error 依赖的类型有问题,不影响使用
|
|
158
280
|
"@typescript-eslint": pluginTs
|
|
159
281
|
}
|
|
160
282
|
},
|
|
@@ -180,8 +302,10 @@ async function typescript(options) {
|
|
|
180
302
|
rules: {
|
|
181
303
|
...pluginTs.configs.strict.rules,
|
|
182
304
|
"@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": "allow-with-description" }],
|
|
305
|
+
"@typescript-eslint/no-shadow": "error",
|
|
306
|
+
"@typescript-eslint/no-non-null-assertion": "error",
|
|
307
|
+
"@typescript-eslint/no-empty-function": "error",
|
|
183
308
|
"@typescript-eslint/no-explicit-any": "off",
|
|
184
|
-
"@typescript-eslint/no-non-null-assertion": "off",
|
|
185
309
|
"@typescript-eslint/no-unused-expressions": ["error", {
|
|
186
310
|
allowShortCircuit: true,
|
|
187
311
|
allowTaggedTemplates: true,
|
|
@@ -232,7 +356,7 @@ async function vue(options) {
|
|
|
232
356
|
...pluginVue.configs["flat/recommended"].map((c) => c.rules).reduce((prev, curr) => ({ ...prev, ...curr }), {}),
|
|
233
357
|
...pluginVue.configs["flat/essential"].map((c) => c.rules).reduce((prev, curr) => ({ ...prev, ...curr }), {}),
|
|
234
358
|
...pluginVue.configs["flat/strongly-recommended"].map((c) => c.rules).reduce((prev, curr) => ({ ...prev, ...curr }), {}),
|
|
235
|
-
"vue/multi-word-component-names": "warn",
|
|
359
|
+
"vue/multi-word-component-names": ["warn", { ignores: ["index"] }],
|
|
236
360
|
"vue/component-name-in-template-casing": ["error", "kebab-case", { "registeredComponentsOnly": true }],
|
|
237
361
|
"vue/max-attributes-per-line": ["error", { "singleline": { "max": 3 } }],
|
|
238
362
|
"vue/prefer-true-attribute-shorthand": ["warn", options?.taro ? "never" : "always"],
|
|
@@ -247,30 +371,42 @@ async function zjutjh(options = {}) {
|
|
|
247
371
|
const {
|
|
248
372
|
vue: enableVue = isPackageExists2("vue"),
|
|
249
373
|
ts: enableTs = isPackageExists2("typescript"),
|
|
250
|
-
taro: enableTaro = isPackageExists2("@tarojs/taro")
|
|
374
|
+
taro: enableTaro = isPackageExists2("@tarojs/taro"),
|
|
375
|
+
codeStyle: enableCodeStyle = true
|
|
251
376
|
} = options;
|
|
252
377
|
const configs = [];
|
|
253
378
|
configs.push(javascript());
|
|
254
|
-
configs.push(
|
|
255
|
-
stylistic({ overrides: getOverrides(options, "stylistic") })
|
|
256
|
-
);
|
|
257
379
|
configs.push(imports());
|
|
258
380
|
const typescriptOptions = resolveSubOptions(options, "ts");
|
|
259
|
-
if (enableTs)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
381
|
+
if (enableTs) {
|
|
382
|
+
configs.push(
|
|
383
|
+
await typescript({
|
|
384
|
+
...typescriptOptions,
|
|
385
|
+
overrides: getOverrides(options, "ts")
|
|
386
|
+
})
|
|
387
|
+
);
|
|
388
|
+
}
|
|
265
389
|
if (enableVue) {
|
|
266
390
|
configs.push(
|
|
267
391
|
await vue({
|
|
268
|
-
ts:
|
|
392
|
+
ts: Boolean(enableTs),
|
|
269
393
|
taro: enableTaro,
|
|
270
394
|
overrides: getOverrides(options, "vue")
|
|
271
395
|
})
|
|
272
396
|
);
|
|
273
397
|
}
|
|
398
|
+
const codeStyleOptions = resolveSubOptions(options, "codeStyle");
|
|
399
|
+
if (enableCodeStyle) {
|
|
400
|
+
if (codeStyleOptions.tool === "formatter") {
|
|
401
|
+
configs.push(await formatter(codeStyleOptions));
|
|
402
|
+
} else {
|
|
403
|
+
configs.push(
|
|
404
|
+
stylistic({
|
|
405
|
+
overrides: getOverrides(options, "stylistic")
|
|
406
|
+
})
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
274
410
|
return configs.flat(1);
|
|
275
411
|
}
|
|
276
412
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zjutjh/eslint-config",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.2",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "zjutjh",
|
|
7
7
|
"description": "Eslint config used by zjutjh",
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
],
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
-
"import": "./dist/index.js"
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
14
15
|
}
|
|
15
16
|
},
|
|
16
|
-
"types": "./dist/index.d.ts",
|
|
17
17
|
"engines": {
|
|
18
18
|
"node": ">=18.18.0"
|
|
19
19
|
},
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"@typescript-eslint/parser": "^8.26.1",
|
|
26
26
|
"eslint-plugin-vue": "^10.0.0",
|
|
27
27
|
"vue-eslint-parser": "^10.1.1",
|
|
28
|
-
"eslint": "^9.9.0"
|
|
28
|
+
"eslint": "^9.9.0",
|
|
29
|
+
"eslint-plugin-format": "^1.0.1"
|
|
29
30
|
},
|
|
30
31
|
"peerDependenciesMeta": {
|
|
31
32
|
"@typescript-eslint/eslint-plugin": {
|
|
@@ -39,6 +40,9 @@
|
|
|
39
40
|
},
|
|
40
41
|
"vue-eslint-parser": {
|
|
41
42
|
"optional": true
|
|
43
|
+
},
|
|
44
|
+
"eslint-plugin-format": {
|
|
45
|
+
"optional": true
|
|
42
46
|
}
|
|
43
47
|
},
|
|
44
48
|
"dependencies": {
|
|
@@ -55,6 +59,7 @@
|
|
|
55
59
|
"@typescript-eslint/parser": "^8.26.1",
|
|
56
60
|
"bumpp": "^10.1.0",
|
|
57
61
|
"eslint": "^9.9.0",
|
|
62
|
+
"eslint-plugin-format": "^1.0.1",
|
|
58
63
|
"eslint-plugin-vue": "^10.0.0",
|
|
59
64
|
"jiti": "^2.4.2",
|
|
60
65
|
"tsup": "^8.4.0",
|
|
@@ -66,6 +71,7 @@
|
|
|
66
71
|
"lint": "eslint .",
|
|
67
72
|
"typecheck": "tsc --noEmit",
|
|
68
73
|
"dev": "config-inspector",
|
|
69
|
-
"release": "
|
|
74
|
+
"release": "bumpp && pnpm publish --access public",
|
|
75
|
+
"prepublish": "pnpm build"
|
|
70
76
|
}
|
|
71
77
|
}
|