@zjutjh/eslint-config 2.0.0-beta.0 → 2.0.0-beta.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 CHANGED
@@ -97,14 +97,14 @@ export default zjutjh({
97
97
  overrides: {
98
98
  vue: {
99
99
  "vue/multi-word-component-names": ["off"]
100
- },
101
- stylistic: {
102
- "stylistic/quotes": ["error", "single"]
103
100
  }
104
101
  },
105
102
  ignores: [
106
103
  "**/build"
107
- ]
104
+ ],
105
+ // 默认关闭。设为 true 自动读取项目根目录下的 .gitignore(不存在则跳过)
106
+ // 也可传入 string 指定其他 gitignore 文件路径
107
+ // gitignore: true
108
108
  })
109
109
  ```
110
110
 
@@ -114,11 +114,6 @@ export default zjutjh({
114
114
  export default zjutjh(
115
115
  // 第一个参数是 zjutjh 专用的配置
116
116
  {
117
- overrides: {
118
- stylistic: {
119
- "stylistic/quotes": ["error", "single"]
120
- }
121
- },
122
117
  ignores: [
123
118
  "**/build"
124
119
  ]
@@ -148,16 +143,15 @@ export default zjutjh(
148
143
 
149
144
  ## 代码格式化
150
145
 
151
- 很多人在意代码的格式化,这里单独拿出一章讲。
146
+ 内置 [oxfmt](https://oxc.rs/docs/guide/usage/formatter) 作为格式化工具,**默认开启**,覆盖 js(x)/ts(x)、
147
+ vue、css/scss/less、html、json/jsonc/json5 等文件。
152
148
 
153
- 内置两种格式化工具。`@stylistic/eslint-plugin` (lint 工具对格式的检查) 和传统的 formatter 工具
154
- ([oxfmt](https://oxc.rs/docs/guide/usage/formatter))。stylistic 默认开启,如果要使用 oxfmt,需要手动开启。
149
+ 如果不希望由 ESLint 进行格式化(例如团队另有格式化方案),可以关闭:
155
150
 
156
151
  ```ts
157
- // 启用 oxfmt
158
152
  export default zjutjh({
159
- oxfmt: true
160
- }),
153
+ oxfmt: false
154
+ })
161
155
  ```
162
156
 
163
157
  支持自定义 oxfmt 格式化选项,以及关闭对部分文件的格式化(默认对支持的文件全部开启)
@@ -176,8 +170,7 @@ export default zjutjh({
176
170
  })
177
171
  ```
178
172
 
179
- stylistic 只对 js(x) 和 ts(x) 进行格式化,而 oxfmt 还对其他文件,如 vue,css,html,json 等的格式化。
180
- 如果你要**在编辑器中**自动格式化这些文件,需要配置编辑器来允许 eslint 校验这些类型的文件。
173
+ 如果你要**在编辑器中**自动格式化非 js/ts 的文件,需要配置编辑器来允许 eslint 校验这些类型的文件。
181
174
 
182
175
  ```jsonc
183
176
  // @filename .vscode/settings.json
package/dist/index.d.mts CHANGED
@@ -6,7 +6,6 @@ import { FormatOptions } from "oxfmt";
6
6
  interface OverridesConfigs {
7
7
  vue?: Linter.RulesRecord;
8
8
  ts?: Linter.RulesRecord;
9
- stylistic?: Linter.RulesRecord;
10
9
  react?: Linter.RulesRecord;
11
10
  }
12
11
  interface OptionsConfig extends OptionsComponentExts {
@@ -17,6 +16,7 @@ interface OptionsConfig extends OptionsComponentExts {
17
16
  react?: boolean;
18
17
  oxfmt?: boolean | OptionsOxfmt;
19
18
  ignores?: string[];
19
+ gitignore?: boolean | string;
20
20
  overrides?: OverridesConfigs;
21
21
  }
22
22
  interface OptionsComponentExts {
package/dist/index.mjs CHANGED
@@ -1,10 +1,13 @@
1
1
  import { isPackageExists } from "local-pkg";
2
+ import { existsSync } from "node:fs";
3
+ import { isAbsolute, resolve } from "node:path";
4
+ import { includeIgnoreFile } from "@eslint/compat";
2
5
  import importXPlugin, { flatConfigs } from "eslint-plugin-import-x";
3
6
  import simpleImportSortPlugin from "eslint-plugin-simple-import-sort";
4
7
  import eslintJS from "@eslint/js";
5
8
  import globals from "globals";
6
9
  import uniconPlugin from "eslint-plugin-unicorn";
7
- import pluginStylistic from "@stylistic/eslint-plugin";
10
+ import pluginFormat from "eslint-plugin-format";
8
11
  //#region src/globs.ts
9
12
  const GLOB_VUE = "**/*.vue";
10
13
  const GLOB_JS = "**/*.?([cm])js";
@@ -57,10 +60,18 @@ const GLOBS_EXCLUDES = [
57
60
  //#endregion
58
61
  //#region src/configs/ignores.ts
59
62
  function ignores(options) {
60
- return [{
63
+ const { gitignore = false } = options ?? {};
64
+ const configs = [{
61
65
  name: "zjutjh/ignores",
62
66
  ignores: [...GLOBS_EXCLUDES, ...options?.userIgnores ?? []]
63
67
  }];
68
+ if (gitignore !== false) {
69
+ const path = gitignore === true ? ".gitignore" : gitignore;
70
+ const absolute = isAbsolute(path) ? path : resolve(process.cwd(), path);
71
+ if (existsSync(absolute)) configs.push(includeIgnoreFile(absolute, "zjutjh/gitignore"));
72
+ else if (gitignore !== true) throw new Error(`gitignore file not found: ${absolute}`);
73
+ }
74
+ return configs;
64
75
  }
65
76
  //#endregion
66
77
  //#region src/configs/imports.ts
@@ -108,7 +119,7 @@ function javascript() {
108
119
  name: "zjutjh/javascript/rules",
109
120
  rules: {
110
121
  ...eslintJS.configs.recommended.rules,
111
- "camelcase": "warn",
122
+ camelcase: "warn",
112
123
  "no-warning-comments": "warn",
113
124
  "no-console": ["warn", { allow: [
114
125
  "warn",
@@ -120,7 +131,7 @@ function javascript() {
120
131
  "prefer-const": "warn",
121
132
  "arrow-body-style": "error",
122
133
  "no-nested-ternary": "error",
123
- "curly": "error",
134
+ curly: "error",
124
135
  "no-else-return": "error",
125
136
  "no-implicit-coercion": "error",
126
137
  "no-useless-concat": "error",
@@ -145,31 +156,10 @@ function misc() {
145
156
  plugins: { unicorn: uniconPlugin }
146
157
  }, {
147
158
  name: "zjutjh/misc/rules",
148
- rules: { "unicorn/filename-case": ["error", { "case": "kebabCase" }] }
159
+ rules: { "unicorn/filename-case": ["error", { case: "kebabCase" }] }
149
160
  }];
150
161
  }
151
162
  //#endregion
152
- //#region src/utils.ts
153
- async function interopDefault(m) {
154
- const resolved = await m;
155
- return resolved.default || resolved;
156
- }
157
- async function ensurePackages(packages) {
158
- const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
159
- if (nonExistingPackages.length === 0) return;
160
- if (await (await import("@clack/prompts")).confirm({ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?` })) {
161
- const { installPackage } = await import("@antfu/install-pkg");
162
- await installPackage(nonExistingPackages, { dev: true });
163
- }
164
- }
165
- function resolveSubOptions(options, key) {
166
- if (typeof options[key] === "boolean") return {};
167
- return options[key] || {};
168
- }
169
- function getOverrides(options, key) {
170
- return { ...options.overrides?.[key] };
171
- }
172
- //#endregion
173
163
  //#region src/configs/oxfmt.ts
174
164
  /**
175
165
  * @see https://oxc.rs/docs/guide/usage/formatter
@@ -192,9 +182,7 @@ const oxfmtOptions = {
192
182
  embeddedLanguageFormatting: "auto",
193
183
  singleAttributePerLine: false
194
184
  };
195
- async function oxfmt(options) {
196
- await ensurePackages(["eslint-plugin-format", "oxfmt"]);
197
- const pluginFormat = await interopDefault(import("eslint-plugin-format"));
185
+ function oxfmt(options) {
198
186
  const { es: enableESFormat = true, html: enableHTMLFormat = true, css: enableCSSFormat = true, json: enableJSONFormat = true } = options?.lang ?? {};
199
187
  const mergedOptions = {
200
188
  ...oxfmtOptions,
@@ -245,6 +233,27 @@ async function oxfmt(options) {
245
233
  ];
246
234
  }
247
235
  //#endregion
236
+ //#region src/utils.ts
237
+ async function interopDefault(m) {
238
+ const resolved = await m;
239
+ return resolved.default || resolved;
240
+ }
241
+ async function ensurePackages(packages) {
242
+ const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
243
+ if (nonExistingPackages.length === 0) return;
244
+ if (await (await import("@clack/prompts")).confirm({ message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?` })) {
245
+ const { installPackage } = await import("@antfu/install-pkg");
246
+ await installPackage(nonExistingPackages, { dev: true });
247
+ }
248
+ }
249
+ function resolveSubOptions(options, key) {
250
+ if (typeof options[key] === "boolean") return {};
251
+ return options[key] || {};
252
+ }
253
+ function getOverrides(options, key) {
254
+ return { ...options.overrides?.[key] };
255
+ }
256
+ //#endregion
248
257
  //#region src/configs/react.ts
249
258
  async function react(options) {
250
259
  await ensurePackages([
@@ -283,45 +292,6 @@ async function react(options) {
283
292
  }];
284
293
  }
285
294
  //#endregion
286
- //#region src/configs/stylistic.ts
287
- function stylistic(options) {
288
- return [{
289
- name: "zjutjh/stylistic/rules",
290
- plugins: { "@stylistic": pluginStylistic },
291
- rules: {
292
- "@stylistic/eol-last": ["error", "always"],
293
- "@stylistic/indent": ["error", 2],
294
- "@stylistic/keyword-spacing": "error",
295
- "@stylistic/key-spacing": "error",
296
- "@stylistic/no-trailing-spaces": "error",
297
- "@stylistic/linebreak-style": ["error", "unix"],
298
- "@stylistic/quotes": ["error", "double"],
299
- "@stylistic/function-call-spacing": "error",
300
- "@stylistic/semi": "error",
301
- "@stylistic/no-multiple-empty-lines": ["warn", { max: 1 }],
302
- "@stylistic/object-curly-spacing": ["error", "always"],
303
- "@stylistic/arrow-spacing": "error",
304
- "@stylistic/block-spacing": "error",
305
- "@stylistic/brace-style": "error",
306
- "@stylistic/comma-dangle": "error",
307
- "@stylistic/no-multi-spaces": "error",
308
- "@stylistic/comma-spacing": "error",
309
- "@stylistic/switch-colon-spacing": "error",
310
- "@stylistic/type-annotation-spacing": "error",
311
- "@stylistic/space-before-blocks": "error",
312
- "@stylistic/space-before-function-paren": ["error", {
313
- "anonymous": "never",
314
- "named": "never",
315
- "asyncArrow": "always"
316
- }],
317
- "@stylistic/space-in-parens": "error",
318
- "@stylistic/space-infix-ops": "error",
319
- "@stylistic/spaced-comment": "error",
320
- ...options.overrides
321
- }
322
- }];
323
- }
324
- //#endregion
325
295
  //#region src/configs/typescript.ts
326
296
  async function typescript(options) {
327
297
  const { componentExts = [], overrides, parserOptions } = options;
@@ -424,9 +394,9 @@ async function vue(options) {
424
394
  "vue/component-name-in-template-casing": [
425
395
  "error",
426
396
  "kebab-case",
427
- { "registeredComponentsOnly": true }
397
+ { registeredComponentsOnly: true }
428
398
  ],
429
- "vue/max-attributes-per-line": ["error", { "singleline": { "max": 3 } }],
399
+ "vue/max-attributes-per-line": ["error", { singleline: { max: 3 } }],
430
400
  "vue/prefer-true-attribute-shorthand": ["warn", options?.taro ? "never" : "always"],
431
401
  ...options?.overrides
432
402
  }
@@ -435,9 +405,12 @@ async function vue(options) {
435
405
  //#endregion
436
406
  //#region src/factory.ts
437
407
  async function zjutjh(options = {}, ...userConfigs) {
438
- const { componentExts = [], vue: enableVue = isPackageExists("vue"), ts: enableTs = isPackageExists("typescript"), taro: enableTaro = isPackageExists("@tarojs/taro"), jsx: enableJSX = isPackageExists("react"), react: enableReact = isPackageExists("react"), ignores: userIgnores, oxfmt: enableOxfmt = false } = options;
408
+ const { componentExts = [], vue: enableVue = isPackageExists("vue"), ts: enableTs = isPackageExists("typescript"), taro: enableTaro = isPackageExists("@tarojs/taro"), jsx: enableJSX = isPackageExists("react"), react: enableReact = isPackageExists("react"), ignores: userIgnores, gitignore: enableGitignore = false, oxfmt: enableOxfmt = true } = options;
439
409
  const configs = [];
440
- configs.push(ignores({ userIgnores }), javascript(), imports(), stylistic({ overrides: getOverrides(options, "stylistic") }), misc());
410
+ configs.push(ignores({
411
+ userIgnores,
412
+ gitignore: enableGitignore
413
+ }), javascript(), imports(), misc());
441
414
  if (enableVue) componentExts.push("vue");
442
415
  const typescriptOptions = resolveSubOptions(options, "ts");
443
416
  if (enableTs) configs.push(await typescript({
@@ -453,7 +426,7 @@ async function zjutjh(options = {}, ...userConfigs) {
453
426
  if (enableJSX) configs.push(jsx());
454
427
  if (enableReact) configs.push(await react({ overrides: getOverrides(options, "react") }));
455
428
  const oxfmtOptions = resolveSubOptions(options, "oxfmt");
456
- if (enableOxfmt) configs.push(await oxfmt(oxfmtOptions));
429
+ if (enableOxfmt) configs.push(oxfmt(oxfmtOptions));
457
430
  return configs.flat(1).concat(userConfigs);
458
431
  }
459
432
  //#endregion
package/package.json CHANGED
@@ -1,42 +1,66 @@
1
1
  {
2
2
  "name": "@zjutjh/eslint-config",
3
- "type": "module",
4
- "version": "2.0.0-beta.0",
3
+ "version": "2.0.0-beta.2",
4
+ "description": "ESLint config used by zjutjh",
5
5
  "license": "ISC",
6
6
  "author": "zjutjh",
7
- "description": "ESLint config used by zjutjh",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/zjutjh/eslint-config.git"
10
+ },
8
11
  "files": [
9
12
  "dist"
10
13
  ],
14
+ "type": "module",
11
15
  "exports": {
12
16
  ".": {
13
- "import": "./dist/index.mjs",
14
- "types": "./dist/index.d.mts"
17
+ "types": "./dist/index.d.mts",
18
+ "import": "./dist/index.mjs"
15
19
  }
16
20
  },
17
- "engines": {
18
- "node": ">=24"
19
- },
20
- "repository": {
21
- "type": "git",
22
- "url": "https://github.com/zjutjh/eslint-config.git"
23
- },
24
21
  "publishConfig": {
25
22
  "registry": "https://registry.npmjs.org/"
26
23
  },
27
- "simple-git-hooks": {
28
- "pre-commit": "pnpm lint-staged"
24
+ "dependencies": {
25
+ "@antfu/install-pkg": "^1.1.0",
26
+ "@clack/prompts": "^1.2.0",
27
+ "@eslint/compat": "^2.0.5",
28
+ "@eslint/js": "^10.0.1",
29
+ "eslint-plugin-format": "^2.0.1",
30
+ "eslint-plugin-import-x": "^4.16.2",
31
+ "eslint-plugin-simple-import-sort": "^13.0.0",
32
+ "eslint-plugin-unicorn": "^64.0.0",
33
+ "globals": "^17.5.0",
34
+ "local-pkg": "^1.1.2",
35
+ "oxfmt": "^0.35.0"
36
+ },
37
+ "devDependencies": {
38
+ "@eslint-react/eslint-plugin": "^4.2.3",
39
+ "@eslint/config-inspector": "^2.0.0",
40
+ "@eslint/core": "^1.2.1",
41
+ "@types/node": "^25.6.0",
42
+ "@typescript-eslint/eslint-plugin": "^8.58.2",
43
+ "@typescript-eslint/parser": "^8.58.2",
44
+ "bumpp": "^11.0.1",
45
+ "cspell": "^10.0.0",
46
+ "eslint": "^10.2.1",
47
+ "eslint-plugin-react-hooks": "^7.1.1",
48
+ "eslint-plugin-react-refresh": "^0.5.2",
49
+ "eslint-plugin-vue": "^10.8.0",
50
+ "lint-staged": "^16.4.0",
51
+ "simple-git-hooks": "^2.13.1",
52
+ "tsdown": "^0.21.9",
53
+ "typescript": "^6.0.3",
54
+ "vue-eslint-parser": "^10.4.0"
29
55
  },
30
56
  "peerDependencies": {
31
57
  "@eslint-react/eslint-plugin": "^4.2.3",
32
58
  "@typescript-eslint/eslint-plugin": "^8.58.2",
33
59
  "@typescript-eslint/parser": "^8.58.2",
34
60
  "eslint": "^10.2.1",
35
- "eslint-plugin-format": "^2.0.1",
36
61
  "eslint-plugin-react-hooks": "^7.1.1",
37
62
  "eslint-plugin-react-refresh": "^0.5.2",
38
63
  "eslint-plugin-vue": "^10.8.0",
39
- "oxfmt": "^0.35.0",
40
64
  "vue-eslint-parser": "^10.4.0"
41
65
  },
42
66
  "peerDependenciesMeta": {
@@ -49,9 +73,6 @@
49
73
  "@typescript-eslint/parser": {
50
74
  "optional": true
51
75
  },
52
- "eslint-plugin-format": {
53
- "optional": true
54
- },
55
76
  "eslint-plugin-react-hooks": {
56
77
  "optional": true
57
78
  },
@@ -61,44 +82,15 @@
61
82
  "eslint-plugin-vue": {
62
83
  "optional": true
63
84
  },
64
- "oxfmt": {
65
- "optional": true
66
- },
67
85
  "vue-eslint-parser": {
68
86
  "optional": true
69
87
  }
70
88
  },
71
- "dependencies": {
72
- "@antfu/install-pkg": "^1.1.0",
73
- "@clack/prompts": "^1.2.0",
74
- "@eslint/js": "^10.0.1",
75
- "@stylistic/eslint-plugin": "^5.10.0",
76
- "eslint-plugin-import-x": "^4.16.2",
77
- "eslint-plugin-simple-import-sort": "^13.0.0",
78
- "eslint-plugin-unicorn": "^64.0.0",
79
- "globals": "^17.5.0",
80
- "local-pkg": "^1.1.2"
89
+ "simple-git-hooks": {
90
+ "pre-commit": "pnpm lint-staged"
81
91
  },
82
- "devDependencies": {
83
- "@eslint-react/eslint-plugin": "^4.2.3",
84
- "@eslint/config-inspector": "^2.0.0",
85
- "@eslint/core": "^1.2.1",
86
- "@types/node": "^25.6.0",
87
- "@typescript-eslint/eslint-plugin": "^8.58.2",
88
- "@typescript-eslint/parser": "^8.58.2",
89
- "bumpp": "^11.0.1",
90
- "cspell": "^10.0.0",
91
- "eslint": "^10.2.1",
92
- "eslint-plugin-format": "^2.0.1",
93
- "eslint-plugin-react-hooks": "^7.1.1",
94
- "eslint-plugin-react-refresh": "^0.5.2",
95
- "eslint-plugin-vue": "^10.8.0",
96
- "lint-staged": "^16.4.0",
97
- "oxfmt": "^0.35.0",
98
- "simple-git-hooks": "^2.13.1",
99
- "tsdown": "^0.21.9",
100
- "typescript": "^6.0.3",
101
- "vue-eslint-parser": "^10.4.0"
92
+ "engines": {
93
+ "node": ">=24"
102
94
  },
103
95
  "scripts": {
104
96
  "build": "tsdown",