@blueking/bkui-lint 0.1.0-beta.0 → 0.1.1

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.
@@ -0,0 +1,9 @@
1
+ export default {
2
+ '*.(ts|tsx|js)': [
3
+ 'npx biome check --write --files-ignore-unknown=true --no-errors-on-unmatched --colors=force --max-diagnostics=1000 --diagnostic-level=warn',
4
+ 'npx eslint --cache --fix',
5
+ ],
6
+ 'src/**/*.(vue|scss|css|sass)': ['npx stylelint --cache --fix'],
7
+ '*.json': ['npx biome check --write'],
8
+ '*.{md,yml}': ['npx prettier --ignore-unknown --write'],
9
+ };
@@ -0,0 +1,4 @@
1
+ export default {
2
+ 'pre-commit': 'npx lint-staged --concurrent false',
3
+ 'commit-msg': 'node ./verify-commit.mjs $1',
4
+ };
package/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # @blueking/bkui-lint
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@blueking/bkui-lint.svg)](https://www.npmjs.com/package/@blueking/bkui-lint)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.8+-blue.svg)](https://www.typescriptlang.org/)
6
+
7
+ > 蓝鲸前端通用代码质量检查工具集,提供 ESLint、Prettier、Stylelint、Biome 等工具的标准化配置
8
+
9
+ ## ✨ 特性
10
+
11
+ - 🚀 **开箱即用** - 预配置的 ESLint、Prettier、Stylelint、Biome 规则
12
+ - 🎯 **Vue 3 支持** - 针对 Vue 3 项目优化的代码检查规则
13
+ - 📦 **TypeScript 支持** - 完整的 TypeScript 类型检查配置
14
+ - 🎨 **代码格式化** - 统一的代码风格和格式化规则
15
+ - 🔧 **Git Hooks** - 集成 pre-commit 和 commit-msg 钩子
16
+ - 📝 **提交规范** - 标准化的 commit message 格式检查
17
+ - ⚡ **性能优化** - 基于 Biome 的高性能代码检查
18
+
19
+ ## 📦 安装
20
+
21
+ ```bash
22
+ # 使用 npm
23
+ npm install --save-dev @blueking/bkui-lint
24
+
25
+ # 使用 yarn
26
+ yarn add -D @blueking/bkui-lint
27
+
28
+ # 使用 pnpm
29
+ pnpm add -D @blueking/bkui-lint
30
+ ```
31
+
32
+ ## 🚀 快速开始
33
+
34
+ ### 1. 配置 ESLint
35
+
36
+ 创建 `eslint.config.mjs` 文件:
37
+
38
+ ```javascript
39
+ import bkuiLint from '@blueking/bkui-lint/eslint.mjs';
40
+
41
+ export default bkuiLint;
42
+ ```
43
+
44
+ ### 2. 配置 Prettier
45
+
46
+ 创建 `prettier.config.mjs` 文件:
47
+
48
+ ```javascript
49
+ import prettierConfig from '@blueking/bkui-lint/prettier.mjs';
50
+
51
+ export default prettierConfig;
52
+ ```
53
+
54
+ ### 3. 配置 Stylelint
55
+
56
+ 创建 `stylelint.config.mjs` 文件:
57
+
58
+ ```javascript
59
+ import stylelintConfig from '@blueking/bkui-lint/stylelint.mjs';
60
+
61
+ export default stylelintConfig;
62
+ ```
63
+
64
+ ### 4. 配置 Biome
65
+
66
+ 创建 `biome.json` 文件:
67
+
68
+ ```json
69
+ {
70
+ "extends": ["@blueking/bkui-lint/biome.json"]
71
+ }
72
+ ```
73
+
74
+ ### 5. 配置 Git Hooks
75
+
76
+ 首次使用时执行:
77
+
78
+ ```bash
79
+ npx simple-git-hooks
80
+ ```
81
+
82
+ 在 `package.json` 中添加:
83
+
84
+ ```json
85
+ {
86
+ "simple-git-hooks": {
87
+ "pre-commit": "npx lint-staged --concurrent false",
88
+ "commit-msg": "node ./node_modules/@blueking/bkui-lint/verifiy-commit.mjs $1"
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### 6. 配置 lint-staged
94
+
95
+ 创建 `.lintstagedrc.mjs` 文件:
96
+
97
+ ```javascript
98
+ import lintStagedConfig from '@blueking/bkui-lint/.lintstagedrc.mjs';
99
+
100
+ export default lintStagedConfig;
101
+ ```
102
+
103
+ ## 📋 包含的工具
104
+
105
+ ### ESLint 配置
106
+
107
+ - **基础规则**: 基于 `@eslint/js` 推荐配置
108
+ - **TypeScript 支持**: 使用 `typescript-eslint` 提供完整的 TS 支持
109
+ - **Vue 3 支持**: 集成 `eslint-plugin-vue` 的 Vue 3 推荐规则
110
+ - **代码风格**: 集成 `eslint-plugin-prettier` 和 `eslint-config-prettier`
111
+ - **代码质量**: 集成腾讯代码规范 `eslint-config-tencent`
112
+ - **代码排序**: 使用 `eslint-plugin-perfectionist` 自动排序导入、属性等
113
+ - **自定义规则**: 包含针对蓝鲸项目的自定义 ESLint 规则
114
+
115
+ ### Prettier 配置
116
+
117
+ - **代码格式化**: 统一的代码风格配置
118
+ - **Vue 支持**: 针对 Vue 文件的特殊格式化规则
119
+ - **TypeScript 支持**: 完整的 TS/TSX 文件格式化
120
+
121
+ ### Stylelint 配置
122
+
123
+ - **CSS/SCSS 支持**: 基于 `stylelint-config-standard-scss`
124
+ - **Vue 样式支持**: 支持 Vue 单文件组件中的样式检查
125
+ - **Less 支持**: 支持 Less 预处理器
126
+ - **代码排序**: 使用 `stylelint-config-recess-order` 进行属性排序
127
+
128
+ ### Biome 配置
129
+
130
+ - **高性能检查**: 基于 Rust 的高性能代码检查
131
+ - **代码格式化**: 快速的代码格式化功能
132
+ - **TypeScript 支持**: 完整的 TS 类型检查
133
+ - **导入排序**: 自动整理和排序导入语句
134
+
135
+ ## 🔧 高级配置
136
+
137
+ ### 自定义 ESLint 规则
138
+
139
+ ```javascript
140
+ import bkuiLint from '@blueking/bkui-lint/eslint.mjs';
141
+
142
+ export default [
143
+ ...bkuiLint,
144
+ {
145
+ rules: {
146
+ // 你的自定义规则
147
+ 'no-console': 'warn',
148
+ },
149
+ },
150
+ ];
151
+ ```
152
+
153
+ ### 自定义 Prettier 配置
154
+
155
+ ```javascript
156
+ import prettierConfig from '@blueking/bkui-lint/prettier.mjs';
157
+
158
+ export default {
159
+ ...prettierConfig,
160
+ // 你的自定义配置
161
+ printWidth: 100,
162
+ };
163
+ ```
164
+
165
+ ### 自定义 Stylelint 配置
166
+
167
+ ```javascript
168
+ import stylelintConfig from '@blueking/bkui-lint/stylelint.mjs';
169
+
170
+ export default {
171
+ ...stylelintConfig,
172
+ rules: {
173
+ ...stylelintConfig.rules,
174
+ // 你的自定义规则
175
+ 'selector-max-id': 2,
176
+ },
177
+ };
178
+ ```
179
+
180
+ ## 📝 提交规范
181
+
182
+ 本工具集包含标准的 commit message 格式检查,支持以下格式:
183
+
184
+ ### 新格式(推荐)
185
+
186
+ ```
187
+ feat: 添加新功能
188
+ fix: 修复 bug
189
+ docs: 文档更新
190
+ style: 代码格式调整
191
+ refactor: 代码重构
192
+ perf: 性能优化
193
+ test: 测试相关
194
+ chore: 构建过程或辅助工具的变动
195
+ ```
196
+
197
+ ### 旧格式(兼容)
198
+
199
+ ```
200
+ feature: 新特性
201
+ bugfix: 线上功能bug
202
+ minor: 不重要的修改
203
+ optimization: 功能优化
204
+ sprintfix: 未上线代码修改
205
+ merge: 分支合并及冲突解决
206
+ ```
207
+
208
+ ## 🛠️ 脚本命令
209
+
210
+ 在 `package.json` 中添加以下脚本:
211
+
212
+ ```json
213
+ {
214
+ "scripts": {
215
+ "lint": "eslint . --ext .js,.ts,.vue",
216
+ "lint:fix": "eslint . --ext .js,.ts,.vue --fix",
217
+ "format": "prettier --write .",
218
+ "stylelint": "stylelint \"src/**/*.{css,scss,vue}\"",
219
+ "stylelint:fix": "stylelint \"src/**/*.{css,scss,vue}\" --fix",
220
+ "biome:check": "biome check .",
221
+ "biome:format": "biome format --write .",
222
+ "prepare": "simple-git-hooks"
223
+ }
224
+ }
225
+ ```
package/biome.json ADDED
@@ -0,0 +1,113 @@
1
+ {
2
+ "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
3
+ "root": true,
4
+ "files": {
5
+ "includes": [
6
+ "**",
7
+ "!node_modules",
8
+ "!*src/monitor-api/modules",
9
+ "!**/*.scss",
10
+ "!**/*.css",
11
+ "!**/*.less",
12
+ "!**/*.sass",
13
+ "!**/*.png",
14
+ "!**/*.svg",
15
+ "!**/*.vue"
16
+ ]
17
+ },
18
+ "vcs": {
19
+ "enabled": true,
20
+ "clientKind": "git"
21
+ },
22
+ "linter": {
23
+ "enabled": true,
24
+ "rules": {
25
+ "recommended": true,
26
+ "suspicious": {
27
+ "noExplicitAny": {
28
+ "level": "warn"
29
+ },
30
+ "noArrayIndexKey": "warn",
31
+ "noConfusingVoidType": {
32
+ "level": "warn",
33
+ "fix": "none"
34
+ }
35
+ },
36
+ "style": {
37
+ "useSelfClosingElements": {
38
+ "fix": "safe",
39
+ "level": "warn"
40
+ },
41
+ "noUnusedTemplateLiteral": {
42
+ "fix": "safe",
43
+ "level": "error"
44
+ },
45
+ "noNonNullAssertion": "warn"
46
+ },
47
+ "complexity": {
48
+ "noBannedTypes": {
49
+ "fix": "safe",
50
+ "level": "error"
51
+ },
52
+ "noForEach": {
53
+ "level": "warn"
54
+ },
55
+ "useArrowFunction": {
56
+ "fix": "none",
57
+ "level": "warn"
58
+ }
59
+ },
60
+ "a11y": {
61
+ "useKeyWithMouseEvents": "off",
62
+ "useKeyWithClickEvents": "off",
63
+ "noSvgWithoutTitle": "off",
64
+ "useValidAnchor": "off",
65
+ "noLabelWithoutControl": "off",
66
+ "noStaticElementInteractions": "off"
67
+ },
68
+ "correctness": {
69
+ "useJsxKeyInIterable": "error",
70
+ "noUnusedVariables": "error",
71
+ "noUnusedImports": "error"
72
+ }
73
+ }
74
+ },
75
+ "formatter": {
76
+ "enabled": true,
77
+ "indentStyle": "space",
78
+ "indentWidth": 2,
79
+ "lineEnding": "lf",
80
+ "lineWidth": 120,
81
+ "attributePosition": "multiline"
82
+ },
83
+ "javascript": {
84
+ "parser": {
85
+ "jsxEverywhere": false
86
+ },
87
+ "linter": {
88
+ "enabled": true
89
+ },
90
+ "formatter": {
91
+ "quoteStyle": "single",
92
+ "jsxQuoteStyle": "single",
93
+ "quoteProperties": "asNeeded",
94
+ "trailingCommas": "es5",
95
+ "semicolons": "always",
96
+ "arrowParentheses": "asNeeded",
97
+ "bracketSpacing": true,
98
+ "bracketSameLine": false,
99
+ "attributePosition": "multiline"
100
+ }
101
+ },
102
+ "assist": {
103
+ "enabled": true,
104
+ "actions": {
105
+ "source": {
106
+ "organizeImports": "off",
107
+ "useSortedAttributes": "off",
108
+ "useSortedKeys": "off",
109
+ "useSortedProperties": "off"
110
+ }
111
+ }
112
+ }
113
+ }
package/eslint.mjs ADDED
@@ -0,0 +1,500 @@
1
+ import jsEslint from '@eslint/js';
2
+ import eslintConfigPrettier from 'eslint-config-prettier';
3
+ import tencentEslintLegacyRules from 'eslint-config-tencent/ts';
4
+ import codecc from 'eslint-plugin-codecc';
5
+ import perfectionist from 'eslint-plugin-perfectionist';
6
+ import prettier from 'eslint-plugin-prettier';
7
+ import eslintVuePlugin from 'eslint-plugin-vue';
8
+ import tsEslint from 'typescript-eslint';
9
+
10
+ const OFF = 0;
11
+ const WARNING = 1;
12
+ const ERROR = 2;
13
+
14
+ const jsxOrVueSortGroups = {
15
+ customGroups: [
16
+ {
17
+ groupName: 'DEFINITION',
18
+ elementNamePattern: ['^is$', '^vIs$', '^v-is$'],
19
+ },
20
+ {
21
+ groupName: 'LIST_RENDERING',
22
+ elementNamePattern: ['^v-for$', '^vFor$'],
23
+ },
24
+ {
25
+ groupName: 'CONDITIONALS',
26
+ elementNamePattern: ['^v-if$', '^v-else-if$', '^v-else$', '^vIf$', '^vElseIf$', '^vElse$'],
27
+ },
28
+ {
29
+ groupName: 'RENDER_MODIFIERS',
30
+ elementNamePattern: ['^v-pre$', '^v-once$', '^vPre$', '^vOnce$'],
31
+ },
32
+ {
33
+ groupName: 'GLOBAL',
34
+ elementNamePattern: '^id$',
35
+ },
36
+ {
37
+ groupName: 'UNIQUE',
38
+ elementNamePattern: ['^ref$', '^key$'],
39
+ },
40
+ {
41
+ groupName: 'WIDTH',
42
+ elementNamePattern: '^width$',
43
+ },
44
+ {
45
+ groupName: 'HEIGHT',
46
+ elementNamePattern: '^height$',
47
+ },
48
+ {
49
+ groupName: 'STYLE',
50
+ elementNamePattern: '^style$',
51
+ },
52
+ {
53
+ groupName: 'CLASS',
54
+ elementNamePattern: ['^class$', '^ext-cls$', '^extCls$'],
55
+ },
56
+ {
57
+ groupName: 'TWO_WAY_BINDING',
58
+ elementNamePattern: ['^v-model$', '^vModel$'],
59
+ },
60
+ {
61
+ groupName: 'SLOT',
62
+ elementNamePattern: ['^v-slot$', '^slot$', '^vSlot$'],
63
+ },
64
+ {
65
+ groupName: 'OTHER_DIRECTIVES',
66
+ elementNamePattern: '^v-',
67
+ },
68
+ {
69
+ groupName: 'EVENTS',
70
+ elementNamePattern: ['^on\\w+', '^v-on', '^vOn', '^@\\w+', '^on-'],
71
+ },
72
+ {
73
+ groupName: 'CONTENT',
74
+ elementNamePattern: ['^v-html$', '^v-text$', '^vHtml$', '^vText$'],
75
+ },
76
+ ],
77
+ groups: [
78
+ 'DEFINITION',
79
+ 'LIST_RENDERING',
80
+ 'CONDITIONALS',
81
+ 'RENDER_MODIFIERS',
82
+ 'GLOBAL',
83
+ 'UNIQUE',
84
+ 'STYLE',
85
+ 'WIDTH',
86
+ 'HEIGHT',
87
+ 'CLASS',
88
+ 'TWO_WAY_BINDING',
89
+ 'SLOT',
90
+ 'OTHER_DIRECTIVES',
91
+ 'multiline',
92
+ 'unknown',
93
+ 'shorthand',
94
+ 'EVENTS',
95
+ ],
96
+ };
97
+ export const vueUnGroupRules = {
98
+ 'vue/require-default-prop': OFF,
99
+ 'vue/attributes-order': [
100
+ ERROR,
101
+ {
102
+ order: [
103
+ 'DEFINITION',
104
+ 'LIST_RENDERING',
105
+ 'CONDITIONALS',
106
+ 'RENDER_MODIFIERS',
107
+ 'GLOBAL',
108
+ 'UNIQUE',
109
+ 'TWO_WAY_BINDING',
110
+ 'SLOT',
111
+ 'OTHER_DIRECTIVES',
112
+ 'OTHER_ATTR',
113
+ 'EVENTS',
114
+ 'CONTENT',
115
+ ],
116
+ alphabetical: true,
117
+ },
118
+ ],
119
+ 'vue/block-lang': [
120
+ 'error',
121
+ {
122
+ script: {
123
+ lang: 'ts',
124
+ allowNoLang: false,
125
+ },
126
+ },
127
+ ],
128
+ };
129
+
130
+ export const createVueEslintConfig = (vueVersion = 3) => {
131
+ const vueConfig =
132
+ vueVersion === 2 ? eslintVuePlugin.configs['flat/vue2-recommended'] : eslintVuePlugin.configs['flat/recommended'];
133
+ return tsEslint.config(jsEslint.configs.recommended, tsEslint.configs.recommended, ...vueConfig, {
134
+ files: ['*.vue', '**/*.vue'],
135
+ languageOptions: {
136
+ parserOptions: {
137
+ parser: '@typescript-eslint/parser',
138
+ },
139
+ },
140
+ rules: {
141
+ ...vueUnGroupRules,
142
+ },
143
+ });
144
+ };
145
+
146
+ export default [
147
+ {
148
+ ignores: ['node_modules', 'dist', '*.json'],
149
+ },
150
+ {
151
+ plugins: { prettier },
152
+ rules: { ...prettier.configs.recommended.rules },
153
+ },
154
+ ...createVueEslintConfig(),
155
+ {
156
+ files: ['*.js', '**/*.js', '*.ts', '**/*.ts'],
157
+ ignores: ['*.tsx', '**/*.tsx', '*.vue', '**/*.vue'],
158
+ plugins: { perfectionist },
159
+ rules: {
160
+ 'perfectionist/sort-classes': [
161
+ ERROR,
162
+ {
163
+ groups: [
164
+ 'decorated-accessor-property',
165
+ 'static-private-method',
166
+ 'private-property',
167
+ 'static-property',
168
+ 'index-signature',
169
+ 'private-method',
170
+ 'static-method',
171
+ 'property',
172
+ 'private-decorated-accessor-property',
173
+ 'private-decorated-property',
174
+ 'decorated-property',
175
+ 'constructor',
176
+ ['get-method', 'set-method'],
177
+ 'decorated-set-method',
178
+ 'decorated-get-method',
179
+ 'decorated-method',
180
+ 'unknown',
181
+ 'method',
182
+ ],
183
+ order: 'asc',
184
+ type: 'natural',
185
+ },
186
+ ],
187
+ },
188
+ },
189
+ {
190
+ plugins: { perfectionist },
191
+ rules: {
192
+ 'perfectionist/sort-enums': [
193
+ ERROR,
194
+ {
195
+ order: 'asc',
196
+ type: 'natural',
197
+ },
198
+ ],
199
+ 'perfectionist/sort-exports': [
200
+ ERROR,
201
+ {
202
+ order: 'asc',
203
+ type: 'natural',
204
+ },
205
+ ],
206
+ 'perfectionist/sort-heritage-clauses': [
207
+ ERROR,
208
+ {
209
+ order: 'asc',
210
+ type: 'natural',
211
+ },
212
+ ],
213
+ 'perfectionist/sort-jsx-props': [
214
+ ERROR,
215
+ {
216
+ ...jsxOrVueSortGroups,
217
+ order: 'asc',
218
+ type: 'natural',
219
+ },
220
+ ],
221
+ 'perfectionist/sort-maps': [
222
+ ERROR,
223
+ {
224
+ order: 'asc',
225
+ type: 'natural',
226
+ },
227
+ ],
228
+ 'perfectionist/sort-imports': [
229
+ ERROR,
230
+ {
231
+ type: 'natural',
232
+ order: 'asc',
233
+ groups: [
234
+ 'top',
235
+ 'vueI18n',
236
+ 'magicBox',
237
+ 'tsxSupport',
238
+ ['builtin', 'external'],
239
+ ['internal', 'sibling', 'parent', 'side-effect', 'index', 'object'],
240
+ 'unknown',
241
+ ['type', 'builtin-type', 'external-type', 'internal-type', 'parent-type', 'sibling-type', 'index-type'],
242
+ ['side-effect-style', 'style'],
243
+ ],
244
+ customGroups: [
245
+ {
246
+ groupName: 'top',
247
+ elementNamePattern: ['./public-path', './public-path.ts', 'monitor-common/polyfill'],
248
+ },
249
+ {
250
+ groupName: 'vueI18n',
251
+ elementNamePattern: ['./i18n/i18n', '^vue$'],
252
+ },
253
+ {
254
+ groupName: 'magicBox',
255
+ elementNamePattern: [
256
+ './common/import-magicbox-ui',
257
+ 'monitor-ui/directive/index',
258
+ 'monitor-static/svg-icons',
259
+ ],
260
+ },
261
+ {
262
+ groupName: 'tsxSupport',
263
+ elementNamePattern: ['vue-property-decorator', 'vue-tsx-support'],
264
+ },
265
+ ],
266
+ fallbackSort: {
267
+ type: 'natural',
268
+ order: 'asc',
269
+ },
270
+ newlinesBetween: 'always',
271
+ internalPattern: ['^@/', '^@router/', '^@store/', '^@page/', '^@static/'],
272
+ sortSideEffects: true,
273
+ },
274
+ ],
275
+ 'perfectionist/sort-interfaces': [
276
+ ERROR,
277
+ {
278
+ order: 'asc',
279
+ type: 'natural',
280
+ groups: ['unknown', 'method', 'multiline-member'],
281
+ },
282
+ ],
283
+ 'perfectionist/sort-intersection-types': [
284
+ ERROR,
285
+ {
286
+ type: 'natural',
287
+ order: 'asc',
288
+ },
289
+ ],
290
+ 'perfectionist/sort-named-exports': [
291
+ ERROR,
292
+ {
293
+ type: 'natural',
294
+ order: 'asc',
295
+ },
296
+ ],
297
+ 'perfectionist/sort-modules': [
298
+ ERROR,
299
+ {
300
+ type: 'natural',
301
+ order: 'asc',
302
+ groups: [
303
+ 'declare-enum',
304
+ 'export-enum',
305
+ 'enum',
306
+ ['declare-interface', 'declare-type'],
307
+ ['export-interface', 'export-type'],
308
+ ['interface', 'type'],
309
+ 'declare-class',
310
+ 'class',
311
+ 'export-class',
312
+ 'declare-function',
313
+ 'export-function',
314
+ 'function',
315
+ ],
316
+ },
317
+ ],
318
+ 'perfectionist/sort-named-imports': [
319
+ ERROR,
320
+ {
321
+ type: 'natural',
322
+ order: 'asc',
323
+ groups: ['type-import', 'value-import', 'unknown'],
324
+ },
325
+ ],
326
+ 'perfectionist/sort-object-types': [
327
+ ERROR,
328
+ {
329
+ type: 'natural',
330
+ order: 'asc',
331
+ },
332
+ ],
333
+ 'perfectionist/sort-union-types': [
334
+ ERROR,
335
+ {
336
+ type: 'natural',
337
+ order: 'asc',
338
+ },
339
+ ],
340
+ 'perfectionist/sort-variable-declarations': [
341
+ ERROR,
342
+ {
343
+ type: 'natural',
344
+ order: 'asc',
345
+ },
346
+ ],
347
+ 'perfectionist/sort-switch-case': OFF,
348
+ 'perfectionist/sort-sets': OFF,
349
+ // 'perfectionist/sort-vue-attributes': [
350
+ // ERROR,
351
+ // {
352
+ // ...jsxOrVueSortGroups,
353
+ // type: 'natural',
354
+ // order: 'asc',
355
+ // },
356
+ // ],
357
+ },
358
+ },
359
+ {
360
+ files: ['*.js', '**/*.js', '*.ts', '**/*.ts', '*.tsx', '**/*.tsx'],
361
+ ignores: [],
362
+ languageOptions: {
363
+ parser: tsEslint.parser,
364
+ parserOptions: {
365
+ ecmaFeatures: { jsx: true, legacyDecorators: true },
366
+ ecmaVersion: 'latest',
367
+ project: true,
368
+ },
369
+ },
370
+ plugins: {
371
+ codecc,
372
+ },
373
+ rules: {
374
+ 'codecc/license': [
375
+ ERROR,
376
+ {
377
+ license: `/*
378
+ * Tencent is pleased to support the open source community by making
379
+ * 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
380
+ *
381
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
382
+ *
383
+ * 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
384
+ *
385
+ * License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
386
+ *
387
+ * ---------------------------------------------------
388
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
389
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
390
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
391
+ * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
392
+ *
393
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
394
+ * the Software.
395
+ *
396
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
397
+ * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
398
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
399
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
400
+ * IN THE SOFTWARE.
401
+ */\n`,
402
+ pattern: '.*Tencent is pleased to support the open source community.+',
403
+ },
404
+ ],
405
+ ...tencentEslintLegacyRules.rules,
406
+ '@typescript-eslint/consistent-type-imports': [
407
+ ERROR,
408
+ {
409
+ prefer: 'type-imports',
410
+ disallowTypeAnnotations: true,
411
+ fixStyle: 'inline-type-imports',
412
+ },
413
+ ],
414
+ },
415
+ },
416
+ eslintConfigPrettier,
417
+ {
418
+ files: ['*.tsx', '*.ts', '*.vue'],
419
+ plugins: {
420
+ 'monitor-vue3': {
421
+ rules: {
422
+ 'no-ref': {
423
+ meta: {
424
+ type: 'suggestion',
425
+ fixable: null,
426
+ messages: {
427
+ // vueuse 推荐
428
+ 'no-ref': `建议使用 shallowRef 替代 ref
429
+ 或使用
430
+ 1、使用 import { ref as deepRef } from 'vue'; deepRef 来替换 ref 的名称;
431
+ 2、使用 import { createRef } from '@vueuse/core'; createRef(initialData, true); 来替换 ref 的名称;`,
432
+ },
433
+ hasSuggestions: true,
434
+ },
435
+ create(context) {
436
+ return {
437
+ CallExpression(node) {
438
+ if (node.callee.type === 'Identifier' && node.callee.name === 'ref') {
439
+ context.report({
440
+ node,
441
+ messageId: 'no-ref',
442
+ });
443
+ }
444
+ },
445
+ };
446
+ },
447
+ },
448
+ },
449
+ },
450
+ },
451
+ rules: {
452
+ 'monitor-vue3/no-ref': WARNING,
453
+ },
454
+ },
455
+ {
456
+ rules: {
457
+ 'no-undef': OFF,
458
+ // 'no-case-declarations': OFF, // biome lint/style/noCaseDeclarations
459
+ // '@typescript-eslint/no-explicit-any': OFF, // biome lint/suspicious/noExplicitAny
460
+ '@typescript-eslint/ban-ts-comment': [
461
+ WARNING,
462
+ {
463
+ minimumDescriptionLength: 0,
464
+ 'ts-check': false,
465
+ 'ts-expect-error': false,
466
+ 'ts-ignore': false,
467
+ 'ts-nocheck': false,
468
+ },
469
+ ],
470
+ // '@typescript-eslint/no-unused-vars': OFF, // biome lint/style/noUnusedVars
471
+ // 'vue/html-self-closing': [
472
+ // ERROR,
473
+ // {
474
+ // html: {
475
+ // void: 'always',
476
+ // normal: 'always',
477
+ // component: 'always',
478
+ // },
479
+ // svg: 'always',
480
+ // math: 'always',
481
+ // },
482
+ // ],
483
+ // '@typescript-eslint/no-unused-expressions': OFF, // biome lint/style/noUnusedExpressions
484
+ // '@typescript-eslint/no-misused-promises': OFF, // biome lint/suspicious/noMisusedPromises
485
+ 'no-async-promise-executor': OFF, // biome lint/suspicious/noAsyncPromiseExecutor
486
+ '@typescript-eslint/no-unused-vars': [
487
+ 'error',
488
+ {
489
+ args: 'all',
490
+ argsIgnorePattern: '^_',
491
+ caughtErrors: 'all',
492
+ caughtErrorsIgnorePattern: '^_',
493
+ destructuredArrayIgnorePattern: '^_',
494
+ varsIgnorePattern: '^_',
495
+ ignoreRestSiblings: true,
496
+ },
497
+ ],
498
+ },
499
+ },
500
+ ];
package/package.json CHANGED
@@ -1,14 +1,18 @@
1
1
  {
2
2
  "name": "@blueking/bkui-lint",
3
- "version": "0.1.0-beta.0",
3
+ "version": "0.1.1",
4
4
  "description": "蓝鲸监控平台公共lint工具",
5
5
  "license": "MIT",
6
6
  "author": "Tencent BlueKing",
7
7
  "module": "index.js",
8
8
  "files": [
9
- "eslint.js",
10
- "prettier.js",
11
- "stylelint.js"
9
+ "eslint.mjs",
10
+ "stylelint.mjs",
11
+ "prettier.mjs",
12
+ "biome.json",
13
+ ".lintstagedrc.mjs",
14
+ ".simple-git-hooks.mjs",
15
+ "verifiy-commit.mjs"
12
16
  ],
13
17
  "publishConfig": {
14
18
  "access": "public",
@@ -34,8 +38,8 @@
34
38
  "stylelint": "^16.22.0",
35
39
  "stylelint-config-recess-order": "^7.1.0",
36
40
  "stylelint-config-recommended-vue": "1.5.0",
37
- "stylelint-config-standard": "^38.0.0",
38
- "stylelint-config-standard-scss": "^15.0.1",
41
+ "stylelint-config-standard": "39.0.0",
42
+ "stylelint-config-standard-scss": "16.0.0",
39
43
  "stylelint-order": "^7.0.0",
40
44
  "stylelint-scss": "^6.12.1",
41
45
  "typescript": "^5.8.3",
package/prettier.mjs ADDED
@@ -0,0 +1,40 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making
3
+ * 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
4
+ *
5
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
6
+ *
7
+ * 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
8
+ *
9
+ * License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
10
+ *
11
+ * ---------------------------------------------------
12
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
14
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15
+ * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
18
+ * the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
21
+ * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
+ * IN THE SOFTWARE.
25
+ */
26
+ export default {
27
+ arrowParens: 'avoid',
28
+ bracketSameLine: false,
29
+ jsxSingleQuote: true,
30
+ printWidth: 120,
31
+ quoteProps: 'as-needed',
32
+ semi: true,
33
+ singleAttributePerLine: true,
34
+ singleQuote: true,
35
+ tabWidth: 2,
36
+ trailingComma: 'all',
37
+ useTabs: false,
38
+ vueIndentScriptAndStyle: true,
39
+ jsxBracketSameLine: false,
40
+ };
package/stylelint.mjs ADDED
@@ -0,0 +1,76 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making
3
+ * 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
4
+ *
5
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
6
+ *
7
+ * 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
8
+ *
9
+ * License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
10
+ *
11
+ * ---------------------------------------------------
12
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
14
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15
+ * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
18
+ * the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
21
+ * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
+ * IN THE SOFTWARE.
25
+ */
26
+ /** @type {import('stylelint').Config} */
27
+ export default {
28
+ extends: ['stylelint-config-recess-order'],
29
+ overrides: [
30
+ {
31
+ extends: ['stylelint-config-standard-scss', 'stylelint-config-recommended-vue/scss'],
32
+ customSyntax: 'postcss-scss',
33
+ files: ['*.scss', '*.css', '**/*.scss', '**/*.css'],
34
+ },
35
+ {
36
+ customSyntax: 'postcss-html',
37
+ files: ['*.vue', './**/*.vue'],
38
+ extends: ['stylelint-config-standard-scss', 'stylelint-config-recommended-vue/scss'],
39
+ rules: {},
40
+ },
41
+ {
42
+ customSyntax: 'postcss-less',
43
+ files: ['*.less', './**/*.less'],
44
+ },
45
+ ],
46
+ plugins: ['stylelint-scss', 'stylelint-order'],
47
+ rules: {
48
+ 'at-rule-no-unknown': [
49
+ true,
50
+ {
51
+ ignoreAtRules: ['/.*/'],
52
+ },
53
+ ],
54
+ 'at-rule-no-vendor-prefix': true,
55
+ 'comment-empty-line-before': ['always', { except: ['first-nested'] }],
56
+ // Sass rules
57
+ 'max-nesting-depth': 10,
58
+ // 不要使用已被 autoprefixer 支持的浏览器前缀
59
+ 'media-feature-name-no-vendor-prefix': true,
60
+ 'order/order': ['declarations', { type: 'at-rule' }, { hasBlock: true, type: 'at-rule' }, 'rules'],
61
+ 'property-no-vendor-prefix': true,
62
+ // 去掉多个import、extends、父子声明之间的空行 --开始
63
+ 'rule-empty-line-before': [
64
+ 'always',
65
+ {
66
+ except: ['first-nested'],
67
+ ignore: ['after-comment'],
68
+ },
69
+ ],
70
+ 'scss/at-extend-no-missing-placeholder': true,
71
+ 'scss/dollar-variable-pattern': '^_?[a-z]+[\\w-]*$',
72
+ 'selector-max-id': 3,
73
+ 'selector-no-vendor-prefix': true,
74
+ 'value-no-vendor-prefix': true,
75
+ },
76
+ };
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making
3
+ * 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
4
+ *
5
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
6
+ *
7
+ * 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
8
+ *
9
+ * License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
10
+ *
11
+ * ---------------------------------------------------
12
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
14
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15
+ * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
18
+ * the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
21
+ * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
+ * IN THE SOFTWARE.
25
+ */
26
+ /*
27
+ ("feat", "A new feature. Correlates with MINOR in SemVer"),
28
+ ("fix", "A bug fix. Correlates with PATCH in SemVer"),
29
+ ("docs", "Documentation only changes"),
30
+ ("style", "Changes that do not affect the meaning of the code"),
31
+ ("refactor", "A code change that neither fixes a bug nor adds a feature"),
32
+ ("perf", "A code change that improves performance"),
33
+ ("test", "Adding missing or correcting existing tests"),
34
+ ("chore", "Changes to the build process or auxiliary tools and libraries such as documentation generation"),
35
+
36
+ # 即将启用的prefix,仍保留一段时间
37
+ ("feature", "新特性"),
38
+ ("bugfix", "线上功能bug"),
39
+ ("minor", "不重要的修改(换行,拼写错误等)"),
40
+ ("optimization", "功能优化"),
41
+ ("sprintfix", "未上线代码修改 (功能模块未上线部分bug)"),
42
+ ("merge", "分支合并及冲突解决"),
43
+ */
44
+ import { readFileSync } from 'node:fs';
45
+ import colors from 'picocolors';
46
+ const msgPath = process.argv[2];
47
+ const msg = readFileSync(msgPath, 'utf-8').trim();
48
+ const oldCommitRE = /^(revert: )?(feature|bugfix|minor|optimization|sprintfix|merge)(\(.+\))?: .{1,50}/;
49
+ const newCommitRE = /^(revert: )?(feat|fix|docs|style|refactor|perf|test|chore)(\(.+\))?: .{1,50}/;
50
+ if (!(oldCommitRE.test(msg) || newCommitRE.test(msg)) && !msg.includes('Merge branch')) {
51
+ console.log(msg);
52
+ console.log('\n');
53
+ console.error(
54
+ ` ${colors.bgRed(colors.white(' ERROR '))} ${colors.red('invalid commit message format.')}\n\n${colors.red(' Proper commit message format is required for automated changelog generation. Examples:\n\n')} ${colors.green("feature: add 'comments' option")}\n` +
55
+ ` ${colors.green('bugfix: handle events on blur (close #28)')}\n}`,
56
+ );
57
+ process.exit(1);
58
+ }