style-code 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ ## 代码风格规范工具
2
+
3
+ ## 运行条件
4
+
5
+ - node18+
6
+
7
+ ## 安装依赖
8
+
9
+ 1. 局部安装 `npm i style-config`
10
+
11
+ 2. 全局安装 `npm i style-config -g`
12
+
13
+ ## 初始化
14
+
15
+ 1. `npx style init`
16
+ 2. 全局安装时可使用 `style init`
17
+
18
+ ## 使用
19
+
20
+ 1. 检查单个文件 `npx eslint yourfile.js`
21
+ 2. 检查单个文件并修复 `npx eslint yourfile.js --fix`
22
+ 3. 检查所有文件 `npm run lint`
23
+ 4. 检查所有文件并修复 `npm run lint:fix`
24
+
25
+ ## 说明
26
+
27
+ 1. 添加代码提交eslint校验修复和提交信息校验,校验成功可提交代码。
28
+ 2. 保存将自动修复代码以及格式化。
29
+ 3. 默认支持vue3,如需校验vue2,可在配置文件`eslint.config.mjs`中修改,更多配置可参考@antfu/eslint文档(https://github.com/antfu/eslint-config/tree/v2.27.3?tab=readme-ov-file)。
30
+ 4. 提交信息格式`type: msg`,例如:`perf: 代码优化`,详情见`commitlint.config.mjs`文件,可自定义规则。
package/bin/index.js ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ const process = require('node:process')
3
+ const { program } = require('commander')
4
+ const { StyleConfigInit } = require('../index')
5
+
6
+ program
7
+ .command('init')
8
+ .description('初始化')
9
+ .action(() => {
10
+ const styleConfigInit = new StyleConfigInit()
11
+
12
+ styleConfigInit.init()
13
+ })
14
+
15
+ program.parse(process.argv)
@@ -0,0 +1,27 @@
1
+ export default {
2
+ // 继承的规则
3
+ extends: ['@commitlint/config-conventional'],
4
+ // 定义规则类型
5
+ rules: {
6
+ // type 类型定义,表示 git 提交的 type 必须在以下类型范围内
7
+ 'type-enum': [
8
+ 2,
9
+ 'always',
10
+ [
11
+ 'feat', // 新功能 feature
12
+ 'fix', // 修复 bug
13
+ 'docs', // 文档注释
14
+ 'format', // 代码格式(不影响代码运行的变动)
15
+ 'perf', // 优化
16
+ 'style', // css样式修改
17
+ 'refactor', // 重构(既不增加新功能,也不是修复bug)
18
+ 'test', // 增加测试
19
+ 'chore', // 构建过程或辅助工具的变动
20
+ 'revert', // 回退
21
+ 'build', // 打包
22
+ ],
23
+ ],
24
+ // subject 大小写不做校验
25
+ 'subject-case': [0],
26
+ },
27
+ }
@@ -0,0 +1,23 @@
1
+ // eslint.config.mjs
2
+ import antfu from '@antfu/eslint-config'
3
+
4
+ export default antfu({
5
+ // 使用Prettier格式化css(css、less、scss)、html、markdown文件
6
+ formatters: {
7
+ css: true,
8
+ html: true,
9
+ markdown: 'prettier',
10
+ },
11
+ vue: true,
12
+ rules: {
13
+ 'no-console': 'off',
14
+ 'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行
15
+ 'no-unexpected-multiline': 'error', // 禁止空余的多行
16
+ 'vue/block-order': [
17
+ 'error',
18
+ {
19
+ order: ['template', 'script', 'style'],
20
+ },
21
+ ], // vue组件代码块顺序
22
+ },
23
+ })
@@ -0,0 +1,2 @@
1
+ # commitlint校验提交备注格式
2
+ npx --no-install commitlint --edit
@@ -0,0 +1,16 @@
1
+ # 获取当前分支
2
+ current_branch=$(git rev-parse --abbrev-ref HEAD)
3
+
4
+ echo -e "\033[33m -------------- 当前分支: $current_branch 正在执行代码commit操作 -------------- \033[0m"
5
+
6
+ # 检查是否有待提交的文件
7
+ if [ -z "$(git diff --cached --name-only)" ]; then
8
+ echo -e "\033[0;31m ************** 暂存区域没有文件 ************** \033[0m"
9
+ exit 1
10
+ fi
11
+
12
+ # 通过lint-staged进行代码检查
13
+ npx --no-install lint-staged
14
+
15
+ echo -e "\033[0;32m -------------- 代码校验通过准备提交 ✅ -------------- \033[0m"
16
+ exit 0
@@ -0,0 +1,50 @@
1
+ module.exports = {
2
+ // Disable the default formatter, use eslint instead
3
+ 'prettier.enable': false,
4
+ 'editor.formatOnSave': false,
5
+
6
+ // Auto fix
7
+ 'editor.codeActionsOnSave': {
8
+ 'source.fixAll.eslint': 'explicit',
9
+ 'source.organizeImports': 'never',
10
+ },
11
+
12
+ // Silent the stylistic rules in you IDE, but still auto fix them
13
+ 'eslint.rules.customizations': [
14
+ { rule: 'style/*', severity: 'off', fixable: true },
15
+ { rule: 'format/*', severity: 'off', fixable: true },
16
+ { rule: '*-indent', severity: 'off', fixable: true },
17
+ { rule: '*-spacing', severity: 'off', fixable: true },
18
+ { rule: '*-spaces', severity: 'off', fixable: true },
19
+ { rule: '*-order', severity: 'off', fixable: true },
20
+ { rule: '*-dangle', severity: 'off', fixable: true },
21
+ { rule: '*-newline', severity: 'off', fixable: true },
22
+ { rule: '*quotes', severity: 'off', fixable: true },
23
+ { rule: '*semi', severity: 'off', fixable: true },
24
+ ],
25
+
26
+ // Enable eslint for all supported languages
27
+ 'eslint.validate': [
28
+ 'javascript',
29
+ 'javascriptreact',
30
+ 'typescript',
31
+ 'typescriptreact',
32
+ 'vue',
33
+ 'html',
34
+ 'markdown',
35
+ 'json',
36
+ 'json5',
37
+ 'jsonc',
38
+ 'yaml',
39
+ 'toml',
40
+ 'xml',
41
+ 'gql',
42
+ 'graphql',
43
+ 'astro',
44
+ 'css',
45
+ 'less',
46
+ 'scss',
47
+ 'pcss',
48
+ 'postcss',
49
+ ],
50
+ }
@@ -0,0 +1,30 @@
1
+ module.exports = [
2
+ {
3
+ name: 'eslint',
4
+ version: '8.57.1',
5
+ },
6
+ {
7
+ name: '@antfu/eslint-config',
8
+ version: '2.27.3',
9
+ },
10
+ {
11
+ name: '@commitlint/cli',
12
+ version: '19.5.0',
13
+ },
14
+ {
15
+ name: '@commitlint/config-conventional',
16
+ version: '19.5.0',
17
+ },
18
+ {
19
+ name: 'lint-staged',
20
+ version: '15.2.10',
21
+ },
22
+ {
23
+ name: 'husky',
24
+ version: '9.1.6',
25
+ },
26
+ {
27
+ name: 'eslint-plugin-format',
28
+ version: '0.1.2',
29
+ },
30
+ ]
package/index.js ADDED
@@ -0,0 +1,242 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('node:fs')
3
+ const process = require('node:process')
4
+ const path = require('node:path')
5
+ const { exec } = require('node:child_process')
6
+ const dependenciesList = require('./const/dependencies')
7
+ const settingsTemplate = require('./config/vscode/settingsTemplate')
8
+
9
+ // 安装依赖并生成配置文件以及配置项
10
+ class StyleConfigInit {
11
+ constructor() {
12
+ this.animate = new StyleConfigAnimate()
13
+ }
14
+
15
+ // 读取文件内容
16
+ readFileContent(filePath) {
17
+ return new Promise((resolve, reject) => {
18
+ fs.readFile(filePath, 'utf8', (err, data) => {
19
+ if (err) {
20
+ reject(new Error(`在读取文件 ${filePath} 时发生错误:${err}`))
21
+ return
22
+ }
23
+ resolve(data)
24
+ })
25
+ })
26
+ }
27
+
28
+ // 写入文件内容
29
+ createFile(filePath, content) {
30
+ return new Promise((resolve, reject) => {
31
+ fs.writeFile(filePath, content, 'utf8', (err) => {
32
+ if (err) {
33
+ reject(new Error(`在写入文件${filePath}时发生错误:${err}`))
34
+ return
35
+ }
36
+ resolve()
37
+ })
38
+ })
39
+ }
40
+
41
+ // 读取模板配置并生成配置文件
42
+ async generateConfigFile(readPath, writePath) {
43
+ const content = await this.readFileContent(readPath)
44
+ await this.createFile(writePath, content)
45
+ }
46
+
47
+ // 安装依赖
48
+ installDependencies() {
49
+ const dependenciesStr = dependenciesList
50
+ .reduce((pre, cur) => {
51
+ return `${pre + cur.name}@${cur.version} `
52
+ }, '')
53
+ .slice(0, -1)
54
+ return new Promise((resolve, reject) => {
55
+ exec(
56
+ `npm install ${dependenciesStr} -D`,
57
+ { cwd: process.cwd() },
58
+ (err, _stdout, _stderr) => {
59
+ if (err) {
60
+ reject(new Error(`在安装依赖时发生错误:${err}`))
61
+ return
62
+ }
63
+ resolve()
64
+ },
65
+ )
66
+ })
67
+ }
68
+
69
+ // 在package.json中添加配置
70
+ async addConfigToPackageJson() {
71
+ const packagePath = path.join(process.cwd(), 'package.json')
72
+ const packageContent = await this.readFileContent(packagePath)
73
+ const packageObj = JSON.parse(packageContent)
74
+ packageObj.scripts = {
75
+ ...packageObj.scripts,
76
+ 'lint': 'eslint .',
77
+ 'lint:fix': 'eslint . --fix',
78
+ 'prepare': 'husky',
79
+ }
80
+ packageObj['lint-staged'] = {
81
+ '*.{js,jsx,ts,tsx,vue}': ['eslint --fix'],
82
+ '*.{scss,less,css,html,md}': ['eslint --fix'],
83
+ }
84
+ await this.createFile(packagePath, JSON.stringify(packageObj, null, 2))
85
+ }
86
+
87
+ // 生成eslint.config.mjs配置文件
88
+ async generateEslintConfig() {
89
+ const templatePath = path.join(__dirname, 'config/eslint/eslintTemplate.js')
90
+ const writePath = path.join(process.cwd(), 'eslint.config.mjs')
91
+ await this.generateConfigFile(templatePath, writePath)
92
+ }
93
+
94
+ // 生成commitlint.config.mjs配置文件
95
+ async generateCommitlintConfig() {
96
+ const templatePath = path.join(__dirname, 'config/commitLint/commitlintTemplate.js')
97
+ const writePath = path.join(process.cwd(), 'commitlint.config.mjs')
98
+ await this.generateConfigFile(templatePath, writePath)
99
+ }
100
+
101
+ // husk初始化
102
+ huskyInit() {
103
+ return new Promise((resolve, reject) => {
104
+ exec(
105
+ `npm run prepare`,
106
+ { cwd: process.cwd() },
107
+ (err, _stdout, _stderr) => {
108
+ if (err) {
109
+ reject(new Error(`在husk初始化时发生错误:${err}`))
110
+ return
111
+ }
112
+ resolve()
113
+ },
114
+ )
115
+ })
116
+ }
117
+
118
+ // husk生成pre-commit钩子和commint-msg钩子
119
+ async huskyGenerateHooks() {
120
+ // 生成commit-msg文件
121
+ const commitMsgTemplate = path.join(__dirname, 'config/gitHooks/commitMsgTemplate')
122
+ const commitMsgWritePath = path.join(process.cwd(), '.husky/commit-msg')
123
+ await this.generateConfigFile(commitMsgTemplate, commitMsgWritePath)
124
+
125
+ // 生成pre-commit文件
126
+ const preCommitTemplate = path.join(__dirname, 'config/gitHooks/preCommitTemplate')
127
+ const preCommitWritePath = path.join(process.cwd(), '.husky/pre-commit')
128
+ await this.generateConfigFile(preCommitTemplate, preCommitWritePath)
129
+ }
130
+
131
+ // 判断文件是否存在
132
+ async fileExists(filePath) {
133
+ try {
134
+ await fs.promises.access(filePath)
135
+ return true
136
+ }
137
+ catch {
138
+ return false
139
+ }
140
+ }
141
+
142
+ // 添加.vscode/settings.json配置
143
+ async addVscodeSettings() {
144
+ // 判断文件是否存在
145
+ const vscodeSettingsPath = path.join(process.cwd(), '.vscode/settings.json')
146
+ const isExists = await this.fileExists(vscodeSettingsPath)
147
+ // 文件存在则合并配置
148
+ if (isExists) {
149
+ const content = await this.readFileContent(vscodeSettingsPath)
150
+ const settingsObj = JSON.parse(content)
151
+ for (const key in settingsTemplate) {
152
+ if (settingsObj[key] !== undefined) {
153
+ console.log(`\nsettings.json中 ${key} 配置项已存在, 未进行更改...`)
154
+ continue
155
+ }
156
+ settingsObj[key] = settingsTemplate[key]
157
+ }
158
+ const settingsJson = JSON.stringify(settingsObj, null, 2)
159
+ await this.createFile(vscodeSettingsPath, settingsJson)
160
+ return
161
+ }
162
+ // 判断文件所在目录是否存在
163
+ const dirPath = path.dirname(vscodeSettingsPath)
164
+ if (!fs.existsSync(dirPath)) {
165
+ // 目录不存在,创建目录
166
+ fs.mkdirSync(dirPath, { recursive: true })
167
+ }
168
+ await this.createFile(
169
+ vscodeSettingsPath,
170
+ JSON.stringify(settingsTemplate, null, 2),
171
+ )
172
+ }
173
+
174
+ // 初始化
175
+ async init() {
176
+ try {
177
+ console.log('\x1B[32m%s\x1B[0m', '************** 正在初始化 ************\n')
178
+ // 动画
179
+ this.animate.start()
180
+
181
+ // 安装依赖
182
+ await this.installDependencies()
183
+
184
+ // 生成eslint.config.mjs配置文件
185
+ await this.generateEslintConfig()
186
+
187
+ // 生成commitlint.config.mjs配置文件
188
+ await this.generateCommitlintConfig()
189
+
190
+ // 在package.json中添加配置
191
+ await this.addConfigToPackageJson()
192
+
193
+ // husky初始化
194
+ await this.huskyInit()
195
+
196
+ // 生成pre-commit钩子和commint-msg钩子文件
197
+ await this.huskyGenerateHooks()
198
+
199
+ // 添加.vscode/settings.json配置
200
+ await this.addVscodeSettings()
201
+
202
+ // 关闭动画
203
+ this.animate.stop()
204
+ console.log('\x1B[32m%s\x1B[0m', '\n\n************** 初始化完成 ************')
205
+ }
206
+ catch (error) {
207
+ // 关闭动画
208
+ this.animate.stop()
209
+ console.error('\n\n出错了:', error)
210
+ }
211
+ }
212
+ }
213
+
214
+ // 动画类
215
+ class StyleConfigAnimate {
216
+ constructor() {
217
+ this.timer = null
218
+ this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
219
+ this.frameIndex = 0
220
+ }
221
+
222
+ // 加载中动画
223
+ animateArrow() {
224
+ process.stdout.write(`\r初始化中...${this.frames[this.frameIndex]}`)
225
+ this.frameIndex = (this.frameIndex + 1) % this.frames.length
226
+ this.timer = setTimeout(() => {
227
+ this.animateArrow()
228
+ }, 100) // 调整速度
229
+ }
230
+
231
+ // 开始动画
232
+ start() {
233
+ this.animateArrow()
234
+ }
235
+
236
+ // 停止动画
237
+ stop() {
238
+ clearTimeout(this.timer)
239
+ }
240
+ }
241
+
242
+ module.exports = { StyleConfigInit }
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "style-code",
3
+ "type": "commonjs",
4
+ "version": "1.0.0",
5
+ "author": "lei",
6
+ "license": "ISC",
7
+ "main": "index.js",
8
+ "bin": {
9
+ "style": "bin/index.js"
10
+ },
11
+ "files": [
12
+ "README.md",
13
+ "bin",
14
+ "config",
15
+ "const",
16
+ "index.js"
17
+ ],
18
+ "dependencies": {
19
+ "commander": "^12.1.0"
20
+ }
21
+ }