@ithinkdt/lint 4.0.0-0

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/src/base.js ADDED
@@ -0,0 +1,198 @@
1
+ import { fixupPluginRules } from '@eslint/compat'
2
+ import { config as tsconfig, configs as tsconfigs } from 'typescript-eslint'
3
+
4
+ import js from '@eslint/js'
5
+ import unicorn from 'eslint-plugin-unicorn'
6
+ import tsdoc from 'eslint-plugin-tsdoc'
7
+ import deprecation from 'eslint-plugin-deprecation'
8
+ import importx from 'eslint-plugin-import'
9
+
10
+ export * as vueparser from 'vue-eslint-parser'
11
+
12
+ export { default as tsparser } from './typescript-eslint-parser-for-extra-files/index.js'
13
+
14
+ export const disableJsTypeChecked = {
15
+ files: ['**/*.js', '**/*.cjs'],
16
+ ...tsconfigs.disableTypeChecked,
17
+ }
18
+
19
+ export default tsconfig(
20
+ js.configs.recommended,
21
+ {
22
+ plugins: { 'import-x': importx },
23
+ settings: {
24
+ 'import-x/extensions': ['.ts', '.tsx', '.js', '.jsx'],
25
+ 'import-x/external-module-folders': ['node_modules', 'node_modules/@types'],
26
+ 'import-x/parsers': {
27
+ '@typescript-eslint/parser': ['.ts', '.tsx', '.cts', '.mts'],
28
+ },
29
+ 'import-x/resolver': {
30
+ node: {
31
+ extensions: ['.ts', '.tsx', '.js', '.cjs', '.jsx'],
32
+ },
33
+ typescript: {
34
+ alwaysTryTypes: true,
35
+ },
36
+ },
37
+ },
38
+ rules: {
39
+ 'import-x/no-unresolved': 'error',
40
+ // 'import-x/named': 'error',
41
+ 'import-x/namespace': 'error',
42
+ 'import-x/default': 'error',
43
+ 'import-x/export': 'error',
44
+ 'import-x/no-named-as-default': 'warn',
45
+ 'import-x/no-named-as-default-member': 'warn',
46
+ 'import-x/no-duplicates': 'warn',
47
+ 'import-x/named': 'off',
48
+ },
49
+ },
50
+ unicorn.configs['flat/recommended'],
51
+ ...tsconfigs.recommendedTypeChecked,
52
+ {
53
+ plugins: {
54
+ tsdoc,
55
+ deprecation: fixupPluginRules(deprecation),
56
+ },
57
+ rules: {
58
+ // ------ start copy from @vue/eslint-config-typescript
59
+
60
+ // The core 'no-unused-vars' rules (in the eslint:recommeded ruleset)
61
+ // does not work with type definitions
62
+ 'no-unused-vars': 'off',
63
+ // TS already checks for that, and Typescript-Eslint recommends to disable it
64
+ // https://typescript-eslint.io/linting/troubleshooting#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
65
+ 'no-undef': 'off',
66
+
67
+ // The following rules are enabled in an `overrides` field in the
68
+ // `@typescript-eslint/recommended` ruleset, only turned on for TypeScript source modules
69
+ // <https://github.com/typescript-eslint/typescript-eslint/blob/cb2d44650d27d8b917e8ce19423245b834db29d2/packages/eslint-plugin/src/configs/eslint-recommended.ts#L27-L30>
70
+
71
+ // But as ESLint cannot precisely target `<script lang="ts">` blocks and skip normal `<script>`,
72
+ // no TypeScript code in `.vue` files would be checked against these rules.
73
+
74
+ // So we now enable them globally.
75
+ // That would also check plain JavaScript files, which diverges a little from
76
+ // the original intention of the `@typescript-eslint/recommended` rulset.
77
+ // But it should be mostly fine.
78
+ 'no-var': 'error', // ts transpiles let/const to var, so no need for vars any more
79
+ 'prefer-const': ['error', { destructuring: 'all' }], // ts provides better types with const
80
+ 'prefer-rest-params': 'error', // ts provides better types with rest args over arguments
81
+ 'prefer-spread': 'error', // ts transpiles spread to apply, so no need for manual apply
82
+
83
+ // this rule, if on, would require explicit return type on the `render` function
84
+ '@typescript-eslint/explicit-function-return-type': 'off',
85
+
86
+ // ------ end
87
+
88
+ // 忽略下划线开始的变量名
89
+ '@typescript-eslint/no-unused-vars': [
90
+ 'warn',
91
+ {
92
+ argsIgnorePattern: '^_',
93
+ varsIgnorePattern: '^_',
94
+ },
95
+ ],
96
+ // 允许非空断言
97
+ '@typescript-eslint/no-non-null-assertion': 'off',
98
+ // 空合并提示
99
+ '@typescript-eslint/prefer-nullish-coalescing': [
100
+ 'warn',
101
+ {
102
+ ignoreConditionalTests: true,
103
+ ignoreTernaryTests: true,
104
+ ignoreMixedLogicalExpressions: true,
105
+ ignorePrimitives: true,
106
+ },
107
+ ],
108
+
109
+ '@typescript-eslint/no-empty-object-type': [
110
+ 'error',
111
+ { allowInterfaces: 'with-single-extends', allowWithName: 'Props$' },
112
+ ],
113
+
114
+ '@typescript-eslint/no-explicit-any': ['error', { ignoreRestArgs: true }],
115
+
116
+ // 允许未 catch 的 promise
117
+ '@typescript-eslint/no-floating-promises': 'off',
118
+ '@typescript-eslint/no-misused-promises': [
119
+ 'warn',
120
+ {
121
+ checksVoidReturn: false,
122
+ },
123
+ ],
124
+ // 允许模版表达式使用数字
125
+ '@typescript-eslint/restrict-template-expressions': [
126
+ 'warn',
127
+ {
128
+ allowNumber: true,
129
+ },
130
+ ],
131
+
132
+ // 允许缩写
133
+ 'unicorn/prevent-abbreviations': ['off'],
134
+
135
+ // 不提升箭头函数
136
+ 'unicorn/consistent-function-scoping': ['warn', { checkArrowFunctions: false }],
137
+
138
+ // 文件名拼写忽略组件
139
+ 'unicorn/filename-case': [
140
+ 'warn',
141
+ {
142
+ case: 'kebabCase',
143
+ ignore: [String.raw`\.(j|t)sx$`, String.raw`\.vue`],
144
+ },
145
+ ],
146
+
147
+ // Array.reduce 设为 警告
148
+ 'unicorn/no-array-reduce': ['warn'],
149
+
150
+ // 重导出检查 忽略已用变量
151
+ 'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }],
152
+
153
+ // tla 设为 警告
154
+ 'unicorn/prefer-top-level-await': ['warn'],
155
+
156
+ // 仅单行时优先三元表达式
157
+ 'unicorn/prefer-ternary': ['warn', 'only-single-line'],
158
+
159
+ // 关闭 优先 String#replaceAll(),使用全局标志进行正则表达式搜索
160
+ 'unicorn/prefer-string-replace-all': ['off'],
161
+
162
+ // 关闭 优先 structuredClone()
163
+ 'unicorn/prefer-structured-clone': 'off',
164
+
165
+ // 与 @typescript-eslint/no-this-alias 重复
166
+ 'unicorn/no-this-assignment': 'off',
167
+
168
+ 'unicorn/template-indent': 'off',
169
+ 'unicorn/empty-brace-spaces': 'off',
170
+ 'unicorn/no-nested-ternary': 'off',
171
+ 'unicorn/number-literal-case': 'off',
172
+ },
173
+ },
174
+ {
175
+ files: ['**/*.ts', '**/*.tsx'],
176
+ rules: {
177
+ // 启用 tsdoc 扫描
178
+ 'tsdoc/syntax': 'warn',
179
+
180
+ // 启用 已弃用API 扫描
181
+ 'deprecation/deprecation': 'error',
182
+ },
183
+ },
184
+ {
185
+ files: ['**/*.d.ts'],
186
+ rules: {
187
+ '@typescript-eslint/no-explicit-any': ['warn', { ignoreRestArgs: true }],
188
+ 'unicorn/no-abusive-eslint-disable': 'off',
189
+ },
190
+ },
191
+ {
192
+ files: ['**/*.cjs'],
193
+ rules: {
194
+ // in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled
195
+ '@typescript-eslint/no-require-imports': 'off',
196
+ },
197
+ },
198
+ )
package/src/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Config } from 'typescript-eslint'
2
+
3
+ declare const config: Config
4
+ export default config
package/src/index.js ADDED
@@ -0,0 +1,108 @@
1
+ import { config as tsconfig } from 'typescript-eslint'
2
+ import vue from 'eslint-plugin-vue'
3
+
4
+ import base, { disableJsTypeChecked, tsparser, vueparser } from './base.js'
5
+
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,
18
+ },
19
+ },
20
+ },
21
+ rules: {
22
+ // 忽略虚拟模块、组件
23
+ 'import-x/no-unresolved': [
24
+ 'error',
25
+ {
26
+ ignore: ['^~', '^virtual:'],
27
+ },
28
+ ],
29
+
30
+ // 关闭 vue 代码风格规则
31
+ 'vue/html-self-closing': 'off',
32
+ 'vue/max-len': 'off',
33
+ 'vue/array-bracket-newline': 'off',
34
+ 'vue/array-bracket-spacing': 'off',
35
+ 'vue/array-element-newline': 'off',
36
+ 'vue/arrow-spacing': 'off',
37
+ 'vue/block-spacing': 'off',
38
+ 'vue/block-tag-newline': 'off',
39
+ 'vue/brace-style': 'off',
40
+ 'vue/comma-dangle': 'off',
41
+ 'vue/comma-spacing': 'off',
42
+ 'vue/comma-style': 'off',
43
+ 'vue/dot-location': 'off',
44
+ 'vue/func-call-spacing': 'off',
45
+ 'vue/html-closing-bracket-newline': 'off',
46
+ 'vue/html-closing-bracket-spacing': 'off',
47
+ 'vue/html-end-tags': 'off',
48
+ 'vue/html-indent': 'off',
49
+ 'vue/html-quotes': 'off',
50
+ 'vue/key-spacing': 'off',
51
+ 'vue/keyword-spacing': 'off',
52
+ 'vue/max-attributes-per-line': 'off',
53
+ 'vue/multiline-html-element-content-newline': 'off',
54
+ 'vue/multiline-ternary': 'off',
55
+ 'vue/mustache-interpolation-spacing': 'off',
56
+ 'vue/no-extra-parens': 'off',
57
+ 'vue/no-multi-spaces': 'off',
58
+ 'vue/no-spaces-around-equal-signs-in-attribute': 'off',
59
+ 'vue/object-curly-newline': 'off',
60
+ 'vue/object-curly-spacing': 'off',
61
+ 'vue/object-property-newline': 'off',
62
+ 'vue/operator-linebreak': 'off',
63
+ 'vue/quote-props': 'off',
64
+ 'vue/script-indent': 'off',
65
+ 'vue/singleline-html-element-content-newline': 'off',
66
+ 'vue/space-in-parens': 'off',
67
+ 'vue/space-infix-ops': 'off',
68
+ 'vue/space-unary-ops': 'off',
69
+ 'vue/template-curly-spacing': 'off',
70
+ },
71
+ },
72
+
73
+ {
74
+ languageOptions: {
75
+ parser: tsparser,
76
+ parserOptions: {
77
+ sourceType: 'module',
78
+ ecmaVersion: 'latest',
79
+ project: true,
80
+ },
81
+ },
82
+ },
83
+ {
84
+ files: ['**/*.vue'],
85
+ languageOptions: {
86
+ parser: vueparser,
87
+ parserOptions: {
88
+ sourceType: 'module',
89
+ ecmaVersion: 'latest',
90
+ parser: {
91
+ js: 'espree',
92
+ jsx: 'espree',
93
+ ts: tsparser,
94
+ tsx: tsparser,
95
+ },
96
+ project: true,
97
+ },
98
+ },
99
+ rules: {
100
+ // 启用 tsdoc 扫描
101
+ 'tsdoc/syntax': 'warn',
102
+
103
+ // 启用 已弃用API 扫描
104
+ 'deprecation/deprecation': 'error',
105
+ },
106
+ },
107
+ disableJsTypeChecked,
108
+ )
@@ -0,0 +1,4 @@
1
+ import { Config } from 'prettier'
2
+
3
+ declare const config: Config
4
+ export default config
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @type {import('prettier').Config}
3
+ */
4
+ export const a = {
5
+ semi: false,
6
+ tabWidth: 4,
7
+ printWidth: 120,
8
+ singleQuote: true,
9
+ endOfLine: 'lf',
10
+ vueIndentScriptAndStyle: false,
11
+ }
12
+
13
+ export default a
@@ -0,0 +1,4 @@
1
+ import { Config } from 'stylelint'
2
+
3
+ declare const config: Config
4
+ export default config
@@ -0,0 +1,49 @@
1
+ import order from 'stylelint-order'
2
+
3
+ import scss from 'stylelint-config-standard-scss'
4
+ import vue from 'stylelint-config-standard-vue'
5
+ import vuescss from 'stylelint-config-standard-vue/scss/index.js'
6
+
7
+ import postcsshtml from 'postcss-html'
8
+ import postcssscss from 'postcss-scss'
9
+
10
+ /**
11
+ * @type {import('stylelint').Config}
12
+ */
13
+ export default {
14
+ extends: [scss, vue, vuescss],
15
+ plugins: [...order],
16
+ overrides: [
17
+ {
18
+ files: ['**/*.(scss|css|vue|html)'],
19
+ customSyntax: postcssscss,
20
+ },
21
+ {
22
+ files: ['**/*.(html|vue)'],
23
+ customSyntax: postcsshtml(),
24
+ },
25
+ ],
26
+ ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts', '**/*.json', '**/*.md', '**/*.yaml'],
27
+ rules: {
28
+ 'no-descending-specificity': [false],
29
+ 'selector-pseudo-element-no-unknown': [
30
+ true,
31
+ {
32
+ ignorePseudoElements: ['v-deep'],
33
+ },
34
+ ],
35
+ 'selector-pseudo-class-no-unknown': [
36
+ true,
37
+ {
38
+ ignorePseudoClasses: ['deep'],
39
+ },
40
+ ],
41
+
42
+ 'selector-class-pattern': [
43
+ /^([a-z][\da-z]*)((-{1,2}|_{1,2})[\da-z]+)*$/,
44
+ {
45
+ message: (selector) => `Expected class selector "${selector}" to be kebab-case or bem`,
46
+ },
47
+ ],
48
+ },
49
+ }
@@ -0,0 +1,67 @@
1
+ import { parser as tsEslintParser } from 'typescript-eslint'
2
+
3
+ import { TSServiceManager } from './ts.js'
4
+
5
+ import { getProjectConfigFiles } from './utils/get-project-config-files.js'
6
+ import { resolveProjectList } from './utils/resolve-project-list.js'
7
+
8
+ export const meta = {
9
+ name: 'typescript-eslint-parser-for-extra-files',
10
+ version: '0.7.0',
11
+ }
12
+
13
+ const DEFAULT_EXTRA_FILE_EXTENSIONS = ['.vue']
14
+ const tsServiceManager = new TSServiceManager()
15
+
16
+ export function parseForESLint(code, options = {}) {
17
+ if (!options.project) {
18
+ return tsEslintParser.parseForESLint(code, options)
19
+ }
20
+ const extraFileExtensions = options.extraFileExtensions || DEFAULT_EXTRA_FILE_EXTENSIONS
21
+ const programs = []
22
+ for (const option of iterateOptions(options)) {
23
+ programs.push(tsServiceManager.getProgram(code, option))
24
+ }
25
+ const filePath = options.filePath
26
+ const parserOptions = {
27
+ ...options,
28
+ filePath,
29
+ programs,
30
+ extraFileExtensions,
31
+ }
32
+ return tsEslintParser.parseForESLint(code, parserOptions)
33
+ }
34
+
35
+ function* iterateOptions(options) {
36
+ if (!options) {
37
+ throw new Error('`parserOptions` is required.')
38
+ }
39
+ if (!options.filePath) {
40
+ throw new Error('`filePath` is required.')
41
+ }
42
+ if (!options.project) {
43
+ throw new Error('Specify `parserOptions.project`. Otherwise there is no point in using this parser.')
44
+ }
45
+ const tsconfigRootDir = typeof options.tsconfigRootDir === 'string' ? options.tsconfigRootDir : process.cwd()
46
+
47
+ for (const project of resolveProjectList({
48
+ project: getProjectConfigFiles({
49
+ project: options.project,
50
+ tsconfigRootDir,
51
+ filePath: options.filePath,
52
+ }),
53
+ projectFolderIgnoreList: options.projectFolderIgnoreList,
54
+ tsconfigRootDir,
55
+ })) {
56
+ yield {
57
+ project,
58
+ filePath: options.filePath,
59
+ extraFileExtensions: options.extraFileExtensions || DEFAULT_EXTRA_FILE_EXTENSIONS,
60
+ }
61
+ }
62
+ }
63
+
64
+ export default {
65
+ meta,
66
+ parseForESLint,
67
+ }
@@ -0,0 +1,28 @@
1
+ import path from 'node:path'
2
+
3
+ import { parse, compileScript } from '@vue/compiler-sfc'
4
+
5
+ export function transformExtraFile(code, context) {
6
+ const ext = path.extname(context.filePath)
7
+ const transform = ext === '.vue' ? transformForVue : () => code
8
+ try {
9
+ return transform(code, context)
10
+ } catch {
11
+ // ignore
12
+ }
13
+
14
+ return code
15
+ }
16
+
17
+ function transformForVue(code, context) {
18
+ if (context.current) {
19
+ return code
20
+ }
21
+ const result = parse(code)
22
+ const compiled = compileScript(result.descriptor, {
23
+ id: 'id',
24
+ reactivityTransform: true,
25
+ })
26
+
27
+ return compiled.content
28
+ }