@ithinkdt/lint 4.0.0-3 → 4.0.0-6

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
@@ -2,14 +2,15 @@
2
2
 
3
3
  安装 `npm i -D @ithinkdt/lint`
4
4
 
5
- - 集成`@eslint/js`的`recommended`推荐规则;
6
- - 集成`eslint-plugin-unicorn`的`flat/recommended`推荐规则;
7
- - 集成`eslint-plugin-vue`的`flat/recommended`推荐规则;
8
- - 集成`typescript-eslint`的`recommendedTypeChecked`,启用`Type Aware Rules 类型感知规则`,检查 ts、vue 文件的类型错误;
9
- - 集成`eslint-plugin-tsdoc`规则;
10
- - 集成`eslint-plugin-deprecation`规则;
11
- - 等待集成`eslint-plugin-import-x`规则;
12
- - 支持`StyleLint、Prettier`配置。
5
+ - 集成 `@eslint/js` 的 `recommended` 推荐规则;
6
+ - 集成 `typescript-eslint` 的 `recommendedTypeChecked`,启用 `Type Aware Rules 类型感知规则`,检查 ts、vue 文件的类型错误;
7
+ - 集成 `eslint-plugin-vue`的`flat/recommended` 推荐规则;
8
+ - 集成 `eslint-plugin-unicorn` `flat/recommended` 推荐规则;
9
+ - 集成 `@unocss/eslint-config` 的 `flat` 推荐规则;
10
+ - 集成 `eslint-plugin-tsdoc` 规则;
11
+ - 集成 `eslint-plugin-import-x` 规则;
12
+ - 集成 `eslint-plugin-playwright`、`@vitest/eslint-plugin` 测试代码规则;
13
+ - 支持 `StyleLint`、`Prettier` 配置。
13
14
 
14
15
  > 由于启用了类型感知规则,原则上 typescript 会在整个项目上执行,推测 `lint-staged` 效果不佳。
15
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ithinkdt/lint",
3
- "version": "4.0.0-3",
3
+ "version": "4.0.0-6",
4
4
  "type": "module",
5
5
  "description": "iThinkDT Cloud Lint",
6
6
  "keywords": [
@@ -32,24 +32,25 @@
32
32
  }
33
33
  },
34
34
  "publishConfig": {
35
- "registry": " https://registry.npmjs.org/",
35
+ "registry": "https://registry.npmjs.org/",
36
36
  "access": "public"
37
37
  },
38
38
  "sideEffects": false,
39
39
  "dependencies": {
40
- "@eslint/compat": "^1.1.1",
41
- "@typescript-eslint/parser": "^8.0.0-alpha.41",
42
- "@vue/compiler-sfc": "^3.4.31",
40
+ "@typescript-eslint/parser": "^8.4.0",
41
+ "@unocss/eslint-config": ">=0.62.3",
42
+ "@vitest/eslint-plugin": "^1.1.0",
43
+ "@vue/compiler-sfc": "^3.5.0",
43
44
  "eslint-import-resolver-custom-alias": "^1.3.2",
44
- "eslint-import-resolver-typescript": "^3.6.1",
45
- "eslint-plugin-deprecation": "^3.0.0",
46
- "eslint-plugin-import": "npm:eslint-plugin-import-x@^3.0.1",
47
- "eslint-plugin-tsdoc": "^0.3.0",
48
- "eslint-plugin-unicorn": "^54.0.0",
49
- "eslint-plugin-vue": "^9.27.0",
45
+ "eslint-import-resolver-typescript": "^3.6.3",
46
+ "eslint-plugin-import": "npm:eslint-plugin-import-x@^4.1.1",
47
+ "eslint-plugin-playwright": "^1.6.2",
48
+ "eslint-plugin-tsdoc": ">=0.3.0",
49
+ "eslint-plugin-unicorn": "^55.0.0",
50
+ "eslint-plugin-vue": "^9.28.0",
50
51
  "globby": "^14.0.2",
51
52
  "is-glob": "^4.0.3",
52
- "postcss": "^8.4.39",
53
+ "postcss": "^8.4.44",
53
54
  "postcss-html": "^1.7.0",
54
55
  "postcss-scss": "^4.0.9",
55
56
  "stylelint-config-recommended": "^14.0.1",
@@ -57,21 +58,23 @@
57
58
  "stylelint-config-standard-scss": "^13.1.0",
58
59
  "stylelint-config-standard-vue": "^1.0.0",
59
60
  "stylelint-order": "^6.0.4",
60
- "stylelint-scss": "^6.4.1",
61
- "typescript-eslint": "^8.0.0-alpha.41",
61
+ "stylelint-scss": "^6.5.1",
62
+ "typescript-eslint": "^8.4.0",
62
63
  "vue-eslint-parser": "^9.4.3"
63
64
  },
64
65
  "peerDependencies": {
65
- "eslint": "^9.0.0",
66
- "stylelint": "^16.0.0",
67
- "prettier": "^3.0.0",
68
- "typescript": "^5.0.0"
66
+ "eslint": ">=8",
67
+ "stylelint": ">=16",
68
+ "prettier": ">=3",
69
+ "dprint": ">=0.47",
70
+ "typescript": ">=5"
69
71
  },
70
72
  "devDependencies": {
71
- "eslint": "^9.6.0",
72
- "prettier": "^3.3.2",
73
- "stylelint": "~16.6.1",
74
- "typescript": "~5.5.3"
73
+ "dprint": ">=0.47.2",
74
+ "eslint": "^9.9.1",
75
+ "prettier": "^3.3.3",
76
+ "stylelint": "~16.9.0",
77
+ "typescript": "~5.5.4"
75
78
  },
76
79
  "license": "MIT",
77
80
  "scripts": {
package/src/base.js CHANGED
@@ -1,17 +1,19 @@
1
1
  import { env } from 'node:process'
2
2
 
3
- import { fixupPluginRules } from '@eslint/compat'
4
3
  import { config as tsconfig, configs as tsconfigs } from 'typescript-eslint'
5
4
 
6
5
  import js from '@eslint/js'
7
6
  import unicorn from 'eslint-plugin-unicorn'
8
7
  import tsdoc from 'eslint-plugin-tsdoc'
9
- import deprecation from 'eslint-plugin-deprecation'
10
8
  import importx from 'eslint-plugin-import'
11
9
 
10
+ export { default as vitest } from '@vitest/eslint-plugin'
11
+ export { default as playwright } from 'eslint-plugin-playwright'
12
+ export { default as vue } from 'eslint-plugin-vue'
13
+
12
14
  export * as vueparser from 'vue-eslint-parser'
13
15
 
14
- export { default as tsparser } from './typescript-eslint-parser-for-extra-files/index.js'
16
+ export { default as tsparser } from './tsparser-for-extra-files/index.js'
15
17
 
16
18
  export const disableJsTypeChecked = {
17
19
  files: ['**/*.js', '**/*.cjs'],
@@ -21,18 +23,17 @@ export const disableJsTypeChecked = {
21
23
  export const IS_CI = !!env.CI
22
24
 
23
25
  export default tsconfig(
24
- js.configs.recommended,
26
+ js.configs['recommended'],
27
+ unicorn.configs['flat/recommended'],
28
+ ...tsconfigs['recommendedTypeChecked'],
29
+ importx.flatConfigs.recommended,
30
+ importx.flatConfigs.typescript,
25
31
  {
26
- plugins: { 'import-x': importx },
32
+ plugins: {
33
+ tsdoc,
34
+ },
27
35
  settings: {
28
- 'import-x/external-module-folders': ['node_modules', 'node_modules/@types'],
29
- 'import-x/parsers': {
30
- '@typescript-eslint/parser': ['.ts', '.tsx', '.cts', '.mts'],
31
- },
32
36
  'import-x/resolver': {
33
- node: {
34
- extensions: ['.ts', '.tsx', '.js', '.cjs', '.jsx'],
35
- },
36
37
  typescript: {
37
38
  alwaysTryTypes: true,
38
39
  },
@@ -41,27 +42,15 @@ export default tsconfig(
41
42
  rules: {
42
43
  // see https://typescript-eslint.io/troubleshooting/typed-linting/performance#eslint-plugin-import
43
44
  'import-x/no-unresolved': 'off',
44
- 'import-x/named': 'off',
45
45
  'import-x/namespace': 'off',
46
46
  'import-x/default': 'off',
47
- 'import-x/export': 'error',
48
- 'import-x/no-named-as-default-member': 'off',
49
- 'import-x/no-duplicates': 'warn',
50
- 'import-x/no-named-as-default': IS_CI ? 'warn' : 'off',
51
- 'import-x/no-unused-modules': IS_CI ? 'error' : 'off',
52
- 'import-x/no-deprecated': IS_CI ? 'error' : 'off',
47
+ 'import-x/no-unused-modules': 'off',
53
48
  'import-x/extensions': 'off',
49
+ 'import-x/no-deprecated': IS_CI ? 'error' : 'off',
50
+ 'import-x/no-named-as-default': IS_CI ? 'warn' : 'off',
51
+ 'import-x/no-named-as-default-member': 'off',
54
52
  'import-x/no-cycle': ['error', { maxDepth: 2, ignoreExternal: true }],
55
- },
56
- },
57
- unicorn.configs['flat/recommended'],
58
- ...tsconfigs.recommendedTypeChecked,
59
- {
60
- plugins: {
61
- tsdoc,
62
- deprecation: fixupPluginRules(deprecation),
63
- },
64
- rules: {
53
+
65
54
  // ------ start copy from @vue/eslint-config-typescript
66
55
 
67
56
  // The core 'no-unused-vars' rules (in the eslint:recommeded ruleset)
@@ -112,7 +101,6 @@ export default tsconfig(
112
101
  ignorePrimitives: true,
113
102
  },
114
103
  ],
115
-
116
104
  '@typescript-eslint/no-empty-object-type': [
117
105
  'error',
118
106
  { allowInterfaces: 'with-single-extends', allowWithName: 'Props$' },
@@ -184,8 +172,8 @@ export default tsconfig(
184
172
  // 启用 tsdoc 扫描
185
173
  'tsdoc/syntax': 'warn',
186
174
 
187
- // 启用 已弃用API 扫描
188
- 'deprecation/deprecation': 'error',
175
+ // 不允许使用标记为 @deprecated 的代码
176
+ '@typescript-eslint/no-deprecated': ['warn'],
189
177
  },
190
178
  },
191
179
  {
package/src/index.d.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  import { Config } from 'typescript-eslint'
2
2
 
3
- declare const config: Config
4
- export default config
3
+ /** Options for {@link lintConfig} */
4
+ export interface LintOptions {
5
+ /** 是否启用 \@unocss/eslint-config */
6
+ unocss?: boolean
7
+ }
8
+
9
+ declare const lintConfig: (options?: LintOptions) => Config
10
+ export default lintConfig
package/src/index.js CHANGED
@@ -1,100 +1,118 @@
1
1
  import { config as tsconfig } from 'typescript-eslint'
2
- import vue from 'eslint-plugin-vue'
3
2
 
4
- import base, { disableJsTypeChecked, tsparser, vueparser } from './base.js'
3
+ import unocss from '@unocss/eslint-config/flat'
5
4
 
6
- export default tsconfig(
7
- ...base,
8
- ...vue.configs['flat/recommended'],
9
- {
10
- settings: {
11
- 'import-x/resolver': {
12
- 'custom-alias': {
13
- alias: { '@': './src' },
14
- extensions: ['.js', '.jsx', '.ts', 'tsx'],
15
- },
16
- typescript: {
17
- project: true,
5
+ import base, { disableJsTypeChecked, tsparser, vueparser, vue, vitest, playwright } from './base.js'
6
+
7
+ export default function config({ unocss: withUnoCSS } = {}) {
8
+ return tsconfig(
9
+ ...base,
10
+ ...vue.configs['flat/recommended'],
11
+ {
12
+ settings: {
13
+ 'import-x/resolver': {
14
+ 'custom-alias': {
15
+ alias: { '@': './src' },
16
+ extensions: ['.js', '.jsx', '.ts', 'tsx'],
17
+ },
18
+ typescript: {
19
+ project: true,
20
+ },
18
21
  },
19
22
  },
23
+ rules: {
24
+ // 将 禁止使用null文字 设为警告
25
+ 'unicorn/no-null': 'warn',
26
+
27
+ // 关闭 vue 代码风格规则
28
+ 'vue/html-self-closing': 'off',
29
+ 'vue/max-len': 'off',
30
+ 'vue/array-bracket-newline': 'off',
31
+ 'vue/array-bracket-spacing': 'off',
32
+ 'vue/array-element-newline': 'off',
33
+ 'vue/arrow-spacing': 'off',
34
+ 'vue/block-spacing': 'off',
35
+ 'vue/block-tag-newline': 'off',
36
+ 'vue/brace-style': 'off',
37
+ 'vue/comma-dangle': 'off',
38
+ 'vue/comma-spacing': 'off',
39
+ 'vue/comma-style': 'off',
40
+ 'vue/dot-location': 'off',
41
+ 'vue/func-call-spacing': 'off',
42
+ 'vue/html-closing-bracket-newline': 'off',
43
+ 'vue/html-closing-bracket-spacing': 'off',
44
+ 'vue/html-end-tags': 'off',
45
+ 'vue/html-indent': 'off',
46
+ 'vue/html-quotes': 'off',
47
+ 'vue/key-spacing': 'off',
48
+ 'vue/keyword-spacing': 'off',
49
+ 'vue/max-attributes-per-line': 'off',
50
+ 'vue/multiline-html-element-content-newline': 'off',
51
+ 'vue/multiline-ternary': 'off',
52
+ 'vue/mustache-interpolation-spacing': 'off',
53
+ 'vue/no-extra-parens': 'off',
54
+ 'vue/no-multi-spaces': 'off',
55
+ 'vue/no-spaces-around-equal-signs-in-attribute': 'off',
56
+ 'vue/object-curly-newline': 'off',
57
+ 'vue/object-curly-spacing': 'off',
58
+ 'vue/object-property-newline': 'off',
59
+ 'vue/operator-linebreak': 'off',
60
+ 'vue/quote-props': 'off',
61
+ 'vue/script-indent': 'off',
62
+ 'vue/singleline-html-element-content-newline': 'off',
63
+ 'vue/space-in-parens': 'off',
64
+ 'vue/space-infix-ops': 'off',
65
+ 'vue/space-unary-ops': 'off',
66
+ 'vue/template-curly-spacing': 'off',
67
+ },
20
68
  },
21
- rules: {
22
- // 关闭 vue 代码风格规则
23
- 'vue/html-self-closing': 'off',
24
- 'vue/max-len': 'off',
25
- 'vue/array-bracket-newline': 'off',
26
- 'vue/array-bracket-spacing': 'off',
27
- 'vue/array-element-newline': 'off',
28
- 'vue/arrow-spacing': 'off',
29
- 'vue/block-spacing': 'off',
30
- 'vue/block-tag-newline': 'off',
31
- 'vue/brace-style': 'off',
32
- 'vue/comma-dangle': 'off',
33
- 'vue/comma-spacing': 'off',
34
- 'vue/comma-style': 'off',
35
- 'vue/dot-location': 'off',
36
- 'vue/func-call-spacing': 'off',
37
- 'vue/html-closing-bracket-newline': 'off',
38
- 'vue/html-closing-bracket-spacing': 'off',
39
- 'vue/html-end-tags': 'off',
40
- 'vue/html-indent': 'off',
41
- 'vue/html-quotes': 'off',
42
- 'vue/key-spacing': 'off',
43
- 'vue/keyword-spacing': 'off',
44
- 'vue/max-attributes-per-line': 'off',
45
- 'vue/multiline-html-element-content-newline': 'off',
46
- 'vue/multiline-ternary': 'off',
47
- 'vue/mustache-interpolation-spacing': 'off',
48
- 'vue/no-extra-parens': 'off',
49
- 'vue/no-multi-spaces': 'off',
50
- 'vue/no-spaces-around-equal-signs-in-attribute': 'off',
51
- 'vue/object-curly-newline': 'off',
52
- 'vue/object-curly-spacing': 'off',
53
- 'vue/object-property-newline': 'off',
54
- 'vue/operator-linebreak': 'off',
55
- 'vue/quote-props': 'off',
56
- 'vue/script-indent': 'off',
57
- 'vue/singleline-html-element-content-newline': 'off',
58
- 'vue/space-in-parens': 'off',
59
- 'vue/space-infix-ops': 'off',
60
- 'vue/space-unary-ops': 'off',
61
- 'vue/template-curly-spacing': 'off',
62
- },
63
- },
64
69
 
65
- {
66
- languageOptions: {
67
- parser: tsparser,
68
- parserOptions: {
69
- sourceType: 'module',
70
- ecmaVersion: 'latest',
71
- project: true,
70
+ {
71
+ languageOptions: {
72
+ parser: tsparser,
73
+ parserOptions: {
74
+ sourceType: 'module',
75
+ ecmaVersion: 'latest',
76
+ project: true,
77
+ },
72
78
  },
73
79
  },
74
- },
75
- {
76
- files: ['**/*.vue'],
77
- languageOptions: {
78
- parser: vueparser,
79
- parserOptions: {
80
- sourceType: 'module',
81
- ecmaVersion: 'latest',
82
- parser: {
83
- js: 'espree',
84
- jsx: 'espree',
85
- ts: tsparser,
86
- tsx: tsparser,
80
+ {
81
+ files: ['**/*.vue'],
82
+ languageOptions: {
83
+ parser: vueparser,
84
+ parserOptions: {
85
+ sourceType: 'module',
86
+ ecmaVersion: 'latest',
87
+ parser: {
88
+ js: 'espree',
89
+ jsx: 'espree',
90
+ ts: tsparser,
91
+ tsx: tsparser,
92
+ },
93
+ project: true,
87
94
  },
88
- project: true,
95
+ },
96
+ rules: {
97
+ // 启用 tsdoc 扫描
98
+ 'tsdoc/syntax': 'warn',
99
+
100
+ // 不允许使用标记为 @deprecated 的代码
101
+ '@typescript-eslint/no-deprecated': ['warn'],
89
102
  },
90
103
  },
91
- rules: {
92
- // 启用 tsdoc 扫描
93
- 'tsdoc/syntax': 'warn',
94
104
 
95
- // 启用 已弃用API 扫描
96
- 'deprecation/deprecation': 'error',
105
+ {
106
+ files: ['tests/unit/**'],
107
+ ...vitest.configs['recommended'],
97
108
  },
98
- },
99
- disableJsTypeChecked,
100
- )
109
+ {
110
+ files: ['tests/e2e/**'],
111
+ ...playwright.configs['flat/recommended'],
112
+ },
113
+
114
+ disableJsTypeChecked,
115
+
116
+ withUnoCSS ? unocss : {},
117
+ )
118
+ }
@@ -0,0 +1,54 @@
1
+ import html from 'prettier/plugins/html'
2
+
3
+ let flag = 0
4
+ function replaceDoc(doc, attrs, parent, i) {
5
+ if (Array.isArray(doc)) {
6
+ for (let i = 0; i < doc.length; i++) {
7
+ replaceDoc(doc[i], attrs, doc, i)
8
+ }
9
+ } else if (typeof doc === 'object' && (doc.type === 'group' || doc.type === 'indent')) {
10
+ for (let i = 0; i < doc.contents.length; i++) {
11
+ replaceDoc(doc.contents[i], attrs, doc.contents, i)
12
+ }
13
+ } else if (parent && typeof doc === 'string') {
14
+ if (flag === 2) {
15
+ parent[i] = `(${doc})`
16
+ flag = 0
17
+ } else if (flag === 0 && attrs.has(doc)) {
18
+ flag = 1
19
+ } else if (flag === 1 && doc === '="') {
20
+ flag = 2
21
+ } else {
22
+ flag = 0
23
+ }
24
+ }
25
+ }
26
+
27
+ export default {
28
+ ...html,
29
+ printers: {
30
+ ...html.printers,
31
+ html: {
32
+ ...html.printers.html,
33
+ print(path, ops, print) {
34
+ const res = html.printers.html.print(path, ops, print)
35
+ if (path.node.type == 'element') {
36
+ const attrs = path.node.attrs.filter((attr) => {
37
+ return (
38
+ attr.value &&
39
+ (attr.name[0] === ':' || (attr.name[0] === 'v' && attr.name[1] === '-')) &&
40
+ attr.value[0] === '(' &&
41
+ attr.value.at(-1) === ')'
42
+ )
43
+ })
44
+
45
+ if (attrs.length > 0) {
46
+ flag = 0
47
+ replaceDoc(res, new Set(attrs.map((attr) => attr.name)))
48
+ }
49
+ }
50
+ return res
51
+ },
52
+ },
53
+ },
54
+ }
package/src/prettier.js CHANGED
@@ -1,13 +1,15 @@
1
+ import path from 'node:path'
1
2
  /**
2
3
  * @type {import('prettier').Config}
3
4
  */
4
- export const a = {
5
+ export const config = {
5
6
  semi: false,
6
7
  tabWidth: 4,
7
8
  printWidth: 120,
8
9
  singleQuote: true,
9
10
  endOfLine: 'lf',
10
11
  vueIndentScriptAndStyle: false,
12
+ plugins: [path.resolve(import.meta.dirname, './prettier-fix-vue.js')],
11
13
  }
12
14
 
13
- export default a
15
+ export default config