前言
工欲善其事,必先利其器。 —— 《论语》
具体到写代码则是需要一套趁手的工具和完整的工作流程,简单讲就是代码产出规范以及自动帮我们进行规范约束的工具
准备
新建项目文件夹,新增index.js
写入以下内容
alert('test')
console.log('test')
eval()
进入文件夹终端,执行以下命令
npm i -g pnpm
pnpm init
统一包管理器
在 package.json
的 scripts
项增加 preinstall
钩子限制项目使用的包管理器,如 npx only-allow pnpm -y
限制使用 pnpm
关于 scripts
钩子可以参考官网文档,对 only-allow
感兴趣的可以看这篇分析:only-allow 源码学习
"scripts": {
"preinstall": "npx only-allow pnpm -y"
}
ESlint
安装 eslint
pnpm i -D eslint
新增 .eslintrc
文件,写入以下 rules
{
// rules 取值 0、1、2,分别是不处理、警告、禁止
"rules": {
"no-eval": 2,
"no-alert": 1, // 禁止使用alert confirm prompt
"no-console": 0
}
}
执行 pnpm eslint "**/*.js"
,得到以下校验结果
1:1 warning Unexpected alert no-alert
3:1 error eval can be harmful no-eval
✖ 2 problems (1 error, 1 warning)
Typescript 支持
pnpm i -D typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin
新增 main.ts
文件,输入以下内容
const toString = Object.prototype.toString
export function is(val: unknown, type: any): boolean {
return toString.call(val) === `[object ${type}]`
}
alert('test')
console.log('s')
eval('')
.eslintrc
修改如下
{
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/no-explicit-any": 2,// 禁用any
"no-eval": 2,
"no-alert": 1, // 禁止使用alert confirm prompt
"no-console": 0
}
}
执行 pnpm eslint "**/*.ts"
得到以下校验结果
2:40 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
5:1 warning Unexpected alert no-alert
7:1 error eval can be harmful no-eval
✖ 3 problems (2 errors, 1 warning)
从上面的例子可以看到 ESLint
还是挺容易配置的,为了方便后面配置,先来了解一些常用配置项
常用配置详解
详细说明请参考 ESLint 配置
parser 和 parserOptions 解析器及其配置
parser
作为主解析器使用,parserOptions
则是针对解析器的一些补充配置,如parserOptions.parser
则可以配置子解析器,也可以针对不同类型文件配置不同的解析器
以 .vue
文件来举例,使用 vue-eslint-parser
进行解析,文件内不同的内容再使用不同解析器
{
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": {
"js": "espree",
"ts": "@typescript-eslint/parser",
"<template>": "espree",
}
}
}
有些库因其内部做了处理只需要配置 parser
即可,比如parser
指定为 @typescript-eslint/parser
也可以处理 js
,比如前面的例子在配置 Typescript
支持后执行 pnpm eslint "**/*.js"
命令同样可以得到检测结果
parserOptions.project
由于项目中可能会使用别名(resolve.alias
)或者有其特殊配置,所以需要指定对应配置才能正确解析
比如下面的配置 @typescript-eslint/parser
解析器会根据 project
指定的 tsconfig.json
的配置对 ts
进行解析,这样对于 ts
文件内路径别名 @
才能正确解析其路径
// .eslintrc
"plugins": ["@typescript-eslint"],
"parserOptions": {
"parser": "@typescript-eslint/parser",
"project": "./tsconfig.json"
},
// tsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"],
"exclude": ["node_modules"]
}
还有一些常用的 parserOptions
配置如 ecmaVersion
指定按照哪个 ecma
版本规范对js
解析, sourceType
用来指定按照哪种模块规范解析js
模块
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
}
extends 和 plugins
不想自己配置繁琐的规则可以使用 extends
去继承对应插件的规则,extends
可以是字符串也可以是字符串数组,关于ESLint
是如何解析和应用extends
字段的可以参看源码applyExtends
以 eslint:
开头的如 eslint:recommended
表示使用 eslint
推荐规则,也有无前缀的如 extends: "airbnb"
,这是继承 eslint-config-airbnb规则的意思
以 plugin:
开头的则表示使用插件拓展规则,如 plugin:jsdoc/recommended
表示使用 jsdoc
插件的推荐规则
需要自定义规则或者extends
对应规则时一般来讲需要配置对应 plugins
以拓展规则,插件名称可以省略 eslint-plugin-
前缀
如果 rules
或者extends
配置了插件的规则而 plugins
没指定对应插件,触发 lint
时可能会因读取不到对应规则而提示失败。
以 eslint-plugin-jsdoc 为例
pnpm i -D eslint-plugin-jsdoc
.eslintrc
修改如下
{
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"plugin:jsdoc/recommended"
],
"rules": {
"no-eval": 2,
"no-alert": 1, // 禁止使用alert confirm prompt
"no-console": 0,
"@typescript-eslint/no-explicit-any": 2
}
}
执行 pnpm eslint "**/*.ts"
得到校验结果可以看到看到 jsdoc
的规则提示
2:8 warning Missing JSDoc comment jsdoc/require-jsdoc
2:40 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
5:1 warning Unexpected alert no-alert
7:1 error eval can be harmful no-eval
✖ 4 problems (2 errors, 2 warnings)
0 errors and 1 warning potentially fixable with the `--fix` option.
不过这里有个小细节就是 plugins
配置项没有配置jsdoc
对应的插件只配置了extends
,这是plugins
机制,自动加载以eslint-plugin-
为前缀的插件
overrides
overrides
通过 files
可以指定不同文件或文件夹进行针对性配置,且其拥有和基础配置项几乎一样的配置,如parserOptions
、extends
、plugins
举个例子,比如只针对utils.ts
设置禁用 any
,main.ts
不限制,utils.ts
内容和main.ts
一样
.eslintrc
修改如下
{
"parser": "@typescript-eslint/parser",
"overrides": [
{
"files": [
"utils.ts"
],
"extends": [
"plugin:jsdoc/recommended"
],
"rules": {
"@typescript-eslint/no-explicit-any": 2,
"no-alert": 1
}
}
],
"plugins": [
"@typescript-eslint"
],
"rules": {
"no-eval": 2,
"no-alert": 1
}
}
执行 pnpm eslint "**/*.ts"
结果如下
// main.ts
5:1 warning Unexpected alert no-alert
7:1 error eval can be harmful no-eval
// utils.ts
2:8 warning Missing JSDoc comment jsdoc/require-jsdoc
2:40 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
5:1 warning Unexpected alert no-alert
7:1 error eval can be harmful no-eval
✖ 6 problems (3 errors, 3 warnings)
0 errors and 1 warning potentially fixable with the `--fix` option.
在 utils.ts
正确书写才能通过校验,jsdoc 文档
/**
* 类型检测
*
* @param {any} val 检测对象
* @param {string} type 类型
* @returns {boolean} 是否属于 type 类型
*/
export function is(val: unknown, type: string): boolean {
return toString.call(val) === `[object ${type}]`
}
rules
rules
有多种写法
- 单取数字值: 0、1、2,分别是关闭、警告、禁止
- 字符串:"off"、"warn"、"error"和上面0、1、2对应
- 数组,第一项可取前两种取值,第二项为该规则的具体配置,不同规则可能支持不同拓展写法,更新详细说明请参照ESlint rules 文档以及对应规则说明
"rules": {
"no-alert": 1,
"quotes": ["error", "double"],
"no-console": [
"error", {
"allow": ["log", "warn", "error", "info"]
}
],
}
globals
有时可能需要一些全局变量的设置以处理
"globals": {
"__DEV__": false,
"__dirname": false,
"define": true,
"history": true,
"location": true,
"wxjs": true,
"$": true,
"WeixinJSBridge": true,
"wx": true,
"process": true,
"qq": true
},
另外 ESLint
还提供 .eslintignore
文件用来屏蔽不需要校验的文件
Stylelint
Stylelint
的配置和 ESLint
实际上是一个思路,这里就不详细介绍了,详细的请参照Stylelint 文档
css
pnpm i -D stylelint stylelint-config-standard
新增index.css
,新增 .stylelintrc
文件,写入以下配置
{
"extends": [
"stylelint-config-standard"
],
"rules": {
"no-empty-first-line": true
}
}
执行 pnpm stylelint "**/*.css"
得到校验结果
index.css
1:1 ✖ Unexpected empty source no-empty-source
1 problem (1 error, 0 warnings)
Scss & Less
pnpm i -D stylelint-scss stylelint-config-recommended-scss
pnpm i -D stylelint-less stylelint-config-recommended-less
.stylelintrc
文件增加 overrides
配置
{
"extends": ["stylelint-config-standard"],
"overrides": [
{
"extends": "stylelint-config-recommended-scss",
"files": ["**/*.scss"]
},
{
"extends": "stylelint-config-recommended-less",
"files": ["**/*.less"]
}
],
"rules": {
"no-empty-first-line": true
},
}
分别建立对应文件执行pnpm stylelint "**/*.{css,scss,less}"
得到以下结果
When linting something other than CSS, you should install an appropriate syntax, e.g. "postcss-less", and use the "customSyntax" option
index.css
1:1 ✖ Unexpected empty source no-empty-source
index.less
1:1 ✖ Unexpected empty source no-empty-source
index.scss
1:1 ✖ Unexpected empty source no-empty-source
3 problems (3 errors, 0 warnings)
提示 less
需要在配置项customSyntax
配置postcss-less
转换器
安装postcss-less
并更改配置如下
{
"extends": [
"stylelint-config-standard"
],
"overrides": [
{
"extends": "stylelint-config-recommended-scss",
"files": [
"**/*.scss"
]
},
{
"extends": "stylelint-config-recommended-less",
"customSyntax": "postcss-less",
"files": [
"**/*.less"
]
}
],
"rules": {
"no-empty-first-line": true
}
}
再次执行 pnpm stylelint "**/*.{css,scss,less}"
关于customSyntax
的配置提示消失
customSyntax
是自定义css
语法转换插件的配置,比如 scss
也有 postcss-scss
,详细说明参照customSyntax 文档
stylelint-config-recess-order
stylelint
的规范推荐加上自动排序规则stylelint-config-recess-order
pnpm i -D stylelint-config-recess-order
.stylelintrc
更改如下
{
"extends": ["stylelint-config-standard", "stylelint-config-recess-order"],
"overrides": [
{
"extends": ["stylelint-config-recommended-scss", "stylelint-config-recess-order"],
"files": ["**/*.scss"]
},
{
"extends": ["stylelint-config-recommended-less", "stylelint-config-recess-order"],
"customSyntax": "postcss-less",
"files": ["**/*.less"]
}
],
"rules": {
"no-empty-first-line": true
}
}
从这里的配置可以看到 overrides
里每一项的 extends
需要单独配置完整的继承关系
和ESLint
一样,Stylelint
提供 .stylelintignore
文件用来屏蔽不需要校验的文件
prettier
ESLint
和 Stylelint
是对js
和css
进行语法规范,代码风格则可以交给prettier来处理
pnpm i -D prettier eslint-config-prettier eslint-plugin-prettier
新增 .prettierrc
文件
{
"printWidth": 140,
"singleQuote": true,
"semi": false,
"trailingComma": "none",
"bracketSameLine": true,
"arrowParens": "avoid",
"htmlWhitespaceSensitivity": "ignore",
"overrides": [
{
// rc 文件按照 json进行格式化
"files": [".prettierrc", ".eslintrc", ".stylelintrc", ".lintstagedrc"],
"options": { "parser": "json" }
}
]
}
prettier
同样提供 .prettierignore
文件用来屏蔽不需要格式化的文件
VScode 配置
当然以上各种 Lint
手动校验实在太累,为了方便可以配合编辑器设置自动格式化,以 VScode
为例
安装对应插件
Prettier - Code formatter
ESLint
Stylelint
Vetur
(vue2)Vue Language Features (Volar)
TypeScript Vue Plugin (Volar)
(如果使用Vue3 + TypeScript
开发 )
新增 .vscode
文件夹,创建 settings.json
配置文件,写入如下简单配置
注意: eslint.workingDirectories 配置项最好指定当前项目的eslint配置文件,这样编辑器的eslint才会根据项目配置进行校验提示
{
"extensions.ignoreRecommendations": false,
"editor.tabSize": 2,
"typescript.updateImportsOnFileMove.enabled": "always",
"javascript.updateImportsOnFileMove.enabled": "always",
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
"editor.fontSize": 14,
"editor.formatOnType": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[vue]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"prettier.semi": false, //结尾分号
"prettier.trailingComma": "none", //结尾逗号
"prettier.singleQuote": true,
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
"eslint.workingDirectories": [".eslintrc", { "mode": "location" }],// 这里需要指定下 .eslintrc ,让编辑器的eslint根据配置去执行校验提示
"eslint.validate": ["vue", "typescript", "javascript", "javascriptreact"]
}
Vue
在 vue
生态链中提供了eslint-plugin-vue库,eslint-plugin-vue 官网 也有详细配置说明,根据说明这里直接选择 vue-eslint-parser
pnpm i -D vue-eslint-parser eslint-plugin-vue
.eslintrc
在 overrides
配置中添加对应 vue
的配置
{
"parser": "vue-eslint-parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"ecmaFeatures": {"jsx": true }
},
"plugins": ["@typescript-eslint"],
"extends": ["prettier"],
"overrides": [
{
"files": ["**/*.{ts,tsx}"],
"extends": ["plugin:jsdoc/recommended"],
"parserOptions": {
"sourceType": "module",
"parser": "@typescript-eslint/parser"
},
"rules": {
"@typescript-eslint/no-explicit-any": 2,
"no-alert": 1
}
},
{
"files": "**/*.vue",
"extends": ["plugin:vue/vue3-recommended", "prettier"],
"rules": {
"@typescript-eslint/no-explicit-any": 2,
"no-alert": 2
},
"parserOptions": {
"sourceType": "module",
"parser": "@typescript-eslint/parser"
}
}
],
"rules": {
"no-eval": 2,
"no-alert": 1
}
}
注意:执行pnpm eslint **/*.vue
进行测试,配置没错的情况下如果有 Failed to load plugin xxx ... Class extends 之类的报错大概率是版本兼容问题
目前 stylelint
是 14.x 版本,在 vue3
的 .vue
文件中有 Unknown word (CssSyntaxError)
错误,解决方案
stylelint
降级到 13 版本以下 ,但是相关的插件都需要处理,相对麻烦- 添加 stylelint-config-html插件来处理
第二种方案比较简单,安装相应插件
pnpm i -D postcss-html stylelint-config-html
.stylelintrc
新增 overrides
配置
{
"extends": [
"stylelint-config-standard",
"stylelint-config-recommended-less",
"stylelint-config-recommended-scss",
"stylelint-config-html/vue",
"stylelint-config-recess-order"
],
"customSyntax": "postcss-html",
"files": [
"**/*.vue"
]
}
这里直接配置 less
和 scss
支持,如不需要都支持只需把extends
中对应的规则删除即可
vue
有许多社区模板可以参考
React
既然 Vue
的配置搞懂了 React
的自然不在话下,所以就不再介绍了,参照React ESLint 插件文档、eslint-plugin-react
配置即可
css-in-js
相关的,如styled-component对应的 lint
有
- stylelint-processor-styled-components(已弃用)
- eslint-plugin-styled-components-a11y
- eslint-plugin-styled-components-css
规范代码提交
代码提交也是很重要的一环,这个环节主要是保证提交上来的代码是符合规范的,包括前文配置的lint
规范、提交日志规范、测试用例等,为此需要定制git hooks
在代码提交上来之前处理好
lint-staged
lint-staged可以来处理不同文件类型需要执行的lint
或其他命令
pnpm i -D lint-staged
package.json
中添加lint-staged
内容,比如下面针对 less
等项目文件的格式化和规范处理
"lint-staged": {
"**/*.less": "stylelint --syntax less",
"(**|!__test__)/*.{jsx,js,tsx,ts,less,md,json,vue}": [
"prettier --write",
"git add"
]
},
也可以使用 .lintstagedrc
文件来配置,如
{
"/src/**/*.{js,jsx,ts,tsx,vue}": ["eslint --cache --fix", "prettier --write"],
"/src/**/*.{css,scss,less}": ["stylelint --cache --fix", "prettier --write"],
"**/*.md": "prettier --write"
}
commitlint
规范提交日志对问题定位和代码回滚有较大的意义
首先当前项目未初始化 git
的先执行 git init
初始化 git
commitizen
使用commitizen、cz-conventional-changelog 来规范日志格式
# 全局安装 commitizen,可能需要根据错误提示执行 pnpm setup ,需重新加载终端或编辑器
pnpm i -g commitizen
# 初始化 cz,会在 package.json 生成commitizen的配置
commitizen init cz-conventional-changelog --pnpm --save-dev --save-exact
# 需要中文的添加 cz-conventional-changelog-zh
pnpm i -D cz-conventional-changelog-zh
commitizen init cz-conventional-changelog --pnpm --save-dev --save-exact
会在 package.json
生成如下配置
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
使用cz-conventional-changelog-zh
的将path
改为./node_modules/cz-conventional-changelog-zh
即可
执行 git cz
会有如下提示(这里使用了中文包),根据提示选择、输入内容即可
? 选择您要提交的更改类型: (Use arrow keys)
> feat: 一个新功能
fix: 一个bug
docs: 文档增删改
style: 样式修改(空白、格式、缺少分号等)
refactor: 既不修复bug也不添加新功能的更改
perf: 性能优化
test: 增加测试
(Move up and down to reveal more choices)
自定义提交规范
新增 commitizen
配置文件 .cz-config.js
-
一种方案是使用 cz-customizable 来改造
.cz-config.js
,支持的配置项可参考cz-customizable/cz-config-EXAMPLE.js -
另外一种方案是自己实现一个规则插件
这里讲讲自实现方式,新增 commit-rules.js
写入自定义规则如下
var configLoader = require('commitizen').configLoader;
const types = [
{
"key": "new-type",
"description": "新类型",
"title": "new-type"
},
{
"key": "feat",
"description": "一个新功能",
"title": "Features"
},
{
"key": "fix",
"description": "一个bug",
"title": "Bug Fixes"
},
]
var config = configLoader.load() || {};
/**
* 交互收集 commit 信息插件
*
* @param cz 提供基础的交互能力
* @param commit 相当于 git commit
*/
function prompter (cz, commit) {
var length = types.length
var defaultType = process.env.CZ_TYPE || config.defaultType
var defaultScope = process.env.CZ_SCOPE || config.defaultScope
var choices = types.map(function ({ key, description }) {
return {
name: (key + ':').padEnd(length) + ' ' + description,
value: key
};
});
cz.prompt([
{
type: 'list',
name: 'type',
message: '选择您要提交的更改类型:',
choices: choices,
default: defaultType
},
{
type: 'input',
name: 'scope',
message: '这个变化的范围是什么(例如组件或文件名):(按回车键跳过)',
default: defaultScope,
filter: function (value) {
return value.trim();
}
},
{
type: 'maxlength-input',
name: 'subject',
message: '写一个简短的修改描述(最多20个字符):\n',
maxLength: 20,
validate: function (subject, answers) {
return subject.length == 0
? '缺少修改描述'
: subject.length <= 20
? true
: '描述内容的长度必须小于或等于20'
},
}
]).then(answers => {
const { type, scope, subject } = answers
var messageScope = scope ? '(' + scope + ')' : '';
const message = `${type}${messageScope}: ${subject} time: ${new Date().getTime()}`
commit(message)
})
}
module.exports = {
prompter
}
.cz-config.js
写入如下内容
{
"path": "./commit-rules"
}
另外项目可能要求只需要本地安装即可,这样 git cz
命令就没法使用,可以换成当前项目内安装commitizen
, package.json
新增 scripts
"scripts": {
"am": "git add . & git-cz",
"cm": "git-cz"
},
执行 pnpm am
得到自定义规则交互提示
> git add . & git-cz
cz-cli@4.3.0, t@1.0.0
? 选择您要提交的更改类型: (Use arrow keys)
> new-type: 新类型
feat: 一个新功能
fix: 一个bug
使用 git cz
或 pnpm git-cz
代替 git commit
用来生成符合规范的 Commit message
husky
然后就是定制git hooks
流程,在 .git/hooks
目录下已经有许多钩子的例子,只需去掉 .sample
后缀钩子便可生效
当然使用 husky 则方便很多
# 安装 husky
pnpm i -D husky
# 未初始化git的需要先初始化git,否则husky会初始化失败
git init
# 初始化husky
pnpm husky install
# 新增钩子文件
npx husky add .husky/pre-commit
npx husky add .husky/commit-msg
commit-msg
文件写入以下内容
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# 校验通过交互收集到的 commit 是否符合规范
pnpm commitlint --edit $1
可以在 package.json
配置 prepare
钩子脚本,保证使用时 husky
已经初始化
"scripts": {
"prepare": "husky install"
}
@commitlint/config-conventional
配合 @commitlint/config-conventional (符合 Angular
风格的校验规则)来使用
pnpm i --save-dev @commitlint/config-conventional
配置 commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional']
}
注意
cz-conventional-changelog-zh
拓展了一些规则和 @commitlint/config-conventional
不完全一样,可以在 commitlint.config.js
拓展
const typesConfig = require('cz-conventional-changelog-zh/src/types.json');
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', Object.keys(typesConfig)]
}
}
如果是参照自定义规则的,也是类似改动
module.exports = {
"extends": ['@commitlint/config-conventional'],
"rules": {
'subject-empty': [0, 'never'],
'type-empty': [0, 'never'],
"type-enum": [
2,
"always",
[
"new-type"
]
]
}
}
当然如果是完全自定的可以不使用 @commitlint/config-conventional
, 可参考 cz-customizable 进行配置
此时执行 pnpm am
根据交互提示最终通过自定义规则可以提交成功
pre-commit
可以参考如下内容
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# 执行 postinstall 钩子
pnpm run postinstall
# 校验lint
npx lint-staged
# 执行测试用例
pnpm test
最后是测试lint-staged
先把pre-commit
内暂时不存在的命令或钩子移除,执行 pnpm am
,会看到触发了 lint-staged
脚本对文件进行了校验,有些不需要检验的文件可以在.eslintignore
、.stylelintignore
、.prettierignore
增加屏蔽配置或者完善lint-staged
匹配规则即可
到此基本过完了所有规范制定和工具集成配置,还是相当繁琐的,尤其是各种插件的组装可能会有各种莫名其妙的报错(大概率是版本问题)
严格还是宽松,如何选择?
有了整个架子就可以按照规范需要去设置对应规则了,至于一个项目要配置多严格的规范,我觉得这要看团队的共识,总的来说有以下两个方向
最终选择感觉主要还是看leader的态度。
还有些更严格的会配置进webpack
等开发工具中时时影响开发过程,个人认为那是在添堵
附录
- 参考
- 可能需要的
ESlint
拓展插件 - 本文使用的各种包的版本参照
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.49.0",
"@typescript-eslint/parser": "^5.49.0",
"cz-conventional-changelog": "^3.3.0",
"cz-conventional-changelog-zh": "^0.0.2",
"eslint": "^8.32.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-jsdoc": "^39.6.8",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.9.0",
"husky": "^8.0.3",
"lint-staged": "^13.1.0",
"postcss-html": "^1.5.0",
"postcss-less": "^6.0.0",
"prettier": "^2.8.3",
"stylelint": "^14.16.1",
"stylelint-config-html": "^1.1.0",
"stylelint-config-recess-order": "^3.1.0",
"stylelint-config-recommended-less": "^1.0.4",
"stylelint-config-recommended-scss": "^8.0.0",
"stylelint-config-standard": "^29.0.0",
"stylelint-less": "^1.0.6",
"stylelint-scss": "^4.3.0",
"typescript": "^4.9.4",
"vue-eslint-parser": "^9.1.0"
},
"dependencies": {
"vue": "^3.2.45"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog-zh"
}
}