@apdesign/code-style-react 1.2.3 → 2.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/.prettierrc.js +10 -10
- package/CHANGELOG.md +157 -0
- package/MIGRATION.md +211 -0
- package/README.md +262 -0
- package/biome.jsonc +99 -0
- package/cli.js +49 -15
- package/index.js +13 -13
- package/lefthook.yml +19 -0
- package/package.json +67 -45
- package/scripts/buildEslint.sh +59 -59
- package/scripts/initConfigs.js +121 -98
- package/scripts/initHusky.js +36 -33
- package/scripts/initScripts.js +39 -36
- package/scripts/runEslint.js +189 -189
- package/scripts/runStylelint.js +137 -137
- package/stylelint/{.stylelintrc.js → rules/.stylelintrc.js} +39 -39
- package/stylelint/rules/color-must-use-variable.js +63 -61
- package/eslint/.eslintrc.build.js +0 -107
- package/eslint/.eslintrc.js +0 -107
package/biome.jsonc
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.2.6/schema.json",
|
3
|
+
"extends": ["ultracite"],
|
4
|
+
"formatter": {
|
5
|
+
"enabled": true,
|
6
|
+
"indentStyle": "space",
|
7
|
+
"indentWidth": 2,
|
8
|
+
"lineWidth": 100
|
9
|
+
},
|
10
|
+
"javascript": {
|
11
|
+
"formatter": {
|
12
|
+
"quoteStyle": "single",
|
13
|
+
"semicolons": "always",
|
14
|
+
"trailingCommas": "all",
|
15
|
+
"bracketSpacing": true,
|
16
|
+
"arrowParentheses": "always"
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"json": {
|
20
|
+
"formatter": {
|
21
|
+
"trailingCommas": "none"
|
22
|
+
}
|
23
|
+
},
|
24
|
+
"linter": {
|
25
|
+
"enabled": true,
|
26
|
+
"rules": {
|
27
|
+
"recommended": false,
|
28
|
+
"a11y": {
|
29
|
+
"noNoninteractiveElementInteractions": "off",
|
30
|
+
"noStaticElementInteractions": "off",
|
31
|
+
"useKeyWithClickEvents": "off"
|
32
|
+
},
|
33
|
+
"complexity": {
|
34
|
+
"noBannedTypes": "error",
|
35
|
+
"noUselessConstructor": "error",
|
36
|
+
"noUselessFragments": "off",
|
37
|
+
"noUselessTypeConstraint": "error",
|
38
|
+
"noForEach": "off"
|
39
|
+
},
|
40
|
+
"correctness": {
|
41
|
+
"noPrecisionLoss": "error",
|
42
|
+
"noUndeclaredVariables": "off",
|
43
|
+
"noUnusedVariables": "warn",
|
44
|
+
"useExhaustiveDependencies": "off"
|
45
|
+
},
|
46
|
+
"style": {
|
47
|
+
"noNamespace": "error",
|
48
|
+
"noParameterAssign": "warn",
|
49
|
+
"useArrayLiterals": "error",
|
50
|
+
"useAsConstAssertion": "error",
|
51
|
+
"useBlockStatements": "off",
|
52
|
+
"useNamingConvention": "off",
|
53
|
+
"useTemplate": "warn",
|
54
|
+
"useFilenamingConvention": "off"
|
55
|
+
},
|
56
|
+
"suspicious": {
|
57
|
+
"noEmptyBlockStatements": "error",
|
58
|
+
"noExplicitAny": "warn",
|
59
|
+
"noExtraNonNullAssertion": "error",
|
60
|
+
"noMisleadingInstantiator": "error",
|
61
|
+
"noUnsafeDeclarationMerging": "error",
|
62
|
+
"noArrayIndexKey": "warn",
|
63
|
+
"noShadowRestrictedNames": "warn",
|
64
|
+
"noConsole": "off"
|
65
|
+
}
|
66
|
+
}
|
67
|
+
},
|
68
|
+
"files": {
|
69
|
+
"includes": [
|
70
|
+
"**/*.js",
|
71
|
+
"**/*.jsx",
|
72
|
+
"**/*.ts",
|
73
|
+
"**/*.tsx",
|
74
|
+
"**/*.json",
|
75
|
+
"**/*.jsonc"
|
76
|
+
],
|
77
|
+
"experimentalScannerIgnores": [
|
78
|
+
"**/dist/**",
|
79
|
+
"**/node_modules/**",
|
80
|
+
"**/*.d.ts",
|
81
|
+
"**/mock/**",
|
82
|
+
"**/.eslintrc.cjs",
|
83
|
+
"**/build/**",
|
84
|
+
"**/coverage/**"
|
85
|
+
]
|
86
|
+
},
|
87
|
+
"overrides": [
|
88
|
+
{
|
89
|
+
"includes": ["scripts/runEslint.js", "scripts/runStylelint.js"],
|
90
|
+
"linter": {
|
91
|
+
"rules": {
|
92
|
+
"complexity": {
|
93
|
+
"noExcessiveCognitiveComplexity": "off"
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
]
|
99
|
+
}
|
package/cli.js
CHANGED
@@ -1,15 +1,49 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
|
3
|
-
const main = require('./index');
|
4
|
-
|
5
|
-
|
6
|
-
const
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
const main = require('./index');
|
4
|
+
const { execSync } = require('node:child_process');
|
5
|
+
|
6
|
+
const args = process.argv.slice(2);
|
7
|
+
const command = args[0];
|
8
|
+
|
9
|
+
if (command === 'init') {
|
10
|
+
main();
|
11
|
+
} else if (command === 'fix') {
|
12
|
+
// 运行 ultracite fix
|
13
|
+
try {
|
14
|
+
execSync('npx ultracite fix', { stdio: 'inherit' });
|
15
|
+
} catch (_error) {
|
16
|
+
process.exit(1);
|
17
|
+
}
|
18
|
+
} else if (command === 'check') {
|
19
|
+
// 运行 ultracite check
|
20
|
+
try {
|
21
|
+
execSync('npx ultracite check', { stdio: 'inherit' });
|
22
|
+
} catch (_error) {
|
23
|
+
process.exit(1);
|
24
|
+
}
|
25
|
+
} else if (command === 'eslint') {
|
26
|
+
// 保留向后兼容的 eslint 命令
|
27
|
+
const runEslint = require('./scripts/runEslint');
|
28
|
+
runEslint(args.slice(1));
|
29
|
+
} else if (command === 'stylelint') {
|
30
|
+
// 保留 stylelint 命令
|
31
|
+
const runStylelint = require('./scripts/runStylelint');
|
32
|
+
runStylelint(args.slice(1));
|
33
|
+
} else {
|
34
|
+
console.log(`
|
35
|
+
Usage: apdesign-code-style <command>
|
36
|
+
|
37
|
+
Commands:
|
38
|
+
init 初始化配置文件(Biome, Stylelint, Husky)
|
39
|
+
fix 格式化并自动修复代码问题(使用 Ultracite)
|
40
|
+
check 检查代码问题但不修复(使用 Ultracite)
|
41
|
+
stylelint 运行 Stylelint 检查样式文件
|
42
|
+
eslint [已废弃] 运行 ESLint(建议使用 fix 或 check)
|
43
|
+
|
44
|
+
Example:
|
45
|
+
apdesign-code-style init
|
46
|
+
apdesign-code-style fix
|
47
|
+
apdesign-code-style check
|
48
|
+
`);
|
49
|
+
}
|
package/index.js
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
|
3
|
-
const initHusky = require('./scripts/initHusky');
|
4
|
-
const initScripts = require('./scripts/initScripts');
|
5
|
-
const initConfigs = require('./scripts/initConfigs');
|
6
|
-
|
7
|
-
function main() {
|
8
|
-
initHusky();
|
9
|
-
initScripts();
|
10
|
-
initConfigs();
|
11
|
-
}
|
12
|
-
|
13
|
-
module.exports = main;
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
const initHusky = require('./scripts/initHusky');
|
4
|
+
const initScripts = require('./scripts/initScripts');
|
5
|
+
const initConfigs = require('./scripts/initConfigs');
|
6
|
+
|
7
|
+
function main() {
|
8
|
+
initHusky();
|
9
|
+
initScripts();
|
10
|
+
initConfigs();
|
11
|
+
}
|
12
|
+
|
13
|
+
module.exports = main;
|
package/lefthook.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
pre-commit:
|
2
|
+
parallel: true
|
3
|
+
commands:
|
4
|
+
# 使用 lint-staged 来运行 Ultracite,会自动处理暂存的文件
|
5
|
+
lint-staged:
|
6
|
+
run: npx lint-staged
|
7
|
+
|
8
|
+
pre-push:
|
9
|
+
parallel: true
|
10
|
+
commands:
|
11
|
+
# 在 push 前检查代码质量
|
12
|
+
biome-check:
|
13
|
+
glob: "*.{js,jsx,ts,tsx,json,jsonc}"
|
14
|
+
run: npx ultracite check {staged_files}
|
15
|
+
|
16
|
+
# 检查样式文件
|
17
|
+
stylelint-check:
|
18
|
+
glob: "*.{css,scss,less}"
|
19
|
+
run: npx stylelint {staged_files}
|
package/package.json
CHANGED
@@ -1,45 +1,67 @@
|
|
1
|
-
{
|
2
|
-
"name": "@apdesign/code-style-react",
|
3
|
-
"version": "
|
4
|
-
"
|
5
|
-
"
|
6
|
-
"
|
7
|
-
|
8
|
-
|
9
|
-
"
|
10
|
-
"
|
11
|
-
"
|
12
|
-
"
|
13
|
-
"
|
14
|
-
"
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
"
|
19
|
-
"
|
20
|
-
"
|
21
|
-
"
|
22
|
-
"
|
23
|
-
|
24
|
-
|
25
|
-
"
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
"
|
30
|
-
|
31
|
-
|
32
|
-
"
|
33
|
-
|
34
|
-
|
35
|
-
"
|
36
|
-
"
|
37
|
-
"
|
38
|
-
"
|
39
|
-
"
|
40
|
-
"stylelint"
|
41
|
-
"
|
42
|
-
"
|
43
|
-
"
|
44
|
-
|
45
|
-
|
1
|
+
{
|
2
|
+
"name": "@apdesign/code-style-react",
|
3
|
+
"version": "2.0.0",
|
4
|
+
"description": "基于 Ultracite (Biome) 的现代化前端代码规范工具集,专为 React/TypeScript 项目设计",
|
5
|
+
"keywords": [
|
6
|
+
"biome",
|
7
|
+
"ultracite",
|
8
|
+
"code-style",
|
9
|
+
"linter",
|
10
|
+
"formatter",
|
11
|
+
"react",
|
12
|
+
"typescript",
|
13
|
+
"eslint",
|
14
|
+
"prettier",
|
15
|
+
"stylelint",
|
16
|
+
"code-quality"
|
17
|
+
],
|
18
|
+
"author": "apdesign",
|
19
|
+
"license": "ISC",
|
20
|
+
"repository": {
|
21
|
+
"type": "git",
|
22
|
+
"url": "https://github.com/apdesign/code-style-react.git"
|
23
|
+
},
|
24
|
+
"bugs": {
|
25
|
+
"url": "https://github.com/apdesign/code-style-react/issues"
|
26
|
+
},
|
27
|
+
"homepage": "https://github.com/apdesign/code-style-react#readme",
|
28
|
+
"scripts": {
|
29
|
+
"prepublishOnly": "npx @biomejs/biome check ."
|
30
|
+
},
|
31
|
+
"bin": {
|
32
|
+
"apdesign-code-style": "cli.js"
|
33
|
+
},
|
34
|
+
"files": [
|
35
|
+
"index.js",
|
36
|
+
"cli.js",
|
37
|
+
".prettierrc.js",
|
38
|
+
"biome.jsonc",
|
39
|
+
"lefthook.yml",
|
40
|
+
"stylelint",
|
41
|
+
"husky",
|
42
|
+
"scripts",
|
43
|
+
"README.md",
|
44
|
+
"CHANGELOG.md",
|
45
|
+
"MIGRATION.md"
|
46
|
+
],
|
47
|
+
"dependencies": {
|
48
|
+
"@biomejs/biome": "^2.2.6",
|
49
|
+
"css-color-names": "^1.0.1",
|
50
|
+
"husky": "^9.1.7",
|
51
|
+
"lefthook": "^1.12.4",
|
52
|
+
"lint-staged": "^16.1.6",
|
53
|
+
"postcss-less": "^6.0.0",
|
54
|
+
"postcss-scss": "^4.0.9",
|
55
|
+
"prettier": "^3.3.3",
|
56
|
+
"stylelint": "^16.19.1",
|
57
|
+
"stylelint-config-standard": "^38.0.0",
|
58
|
+
"stylelint-less": "^3.0.1",
|
59
|
+
"stylelint-scss": "^6.12.0",
|
60
|
+
"ultracite": "^5.6.2"
|
61
|
+
},
|
62
|
+
"lint-staged": {
|
63
|
+
"*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}": [
|
64
|
+
"npx ultracite fix"
|
65
|
+
]
|
66
|
+
}
|
67
|
+
}
|
package/scripts/buildEslint.sh
CHANGED
@@ -1,60 +1,60 @@
|
|
1
|
-
#!/usr/bin/env sh
|
2
|
-
echo "🔍 Starting ESLint check (Git diff files only)..."
|
3
|
-
|
4
|
-
# 切换到 Git 仓库根目录
|
5
|
-
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
6
|
-
cd "$PROJECT_ROOT" || exit 1
|
7
|
-
|
8
|
-
# 参数:commitId(必填),路径(可选)
|
9
|
-
TARGET_COMMIT=$1
|
10
|
-
LATEST_COMMIT=$(git rev-parse HEAD)
|
11
|
-
|
12
|
-
if [ -z "$TARGET_COMMIT" ]; then
|
13
|
-
echo "❗ Error: Missing target commit ID."
|
14
|
-
echo "👉 Usage: $0 <target-commit-id> [project-path]"
|
15
|
-
exit 1
|
16
|
-
fi
|
17
|
-
|
18
|
-
echo "获取到上一次运行commit ID: $TARGET_COMMIT"
|
19
|
-
echo "获取到当前最新的commit ID: $LATEST_COMMIT"
|
20
|
-
|
21
|
-
# 处理路径参数
|
22
|
-
if [ -n "$FULL_PATH" ]; then
|
23
|
-
PROJECT_NAME=$(basename "$FULL_PATH")
|
24
|
-
echo "📂 检测子项目: $PROJECT_NAME"
|
25
|
-
DIFF_FILES=$(git diff --name-only "$TARGET_COMMIT" "$LATEST_COMMIT" -- "*/$PROJECT_NAME/*.{ts,tsx,js,jsx}")
|
26
|
-
else
|
27
|
-
DIFF_FILES=$(git diff --name-only "$TARGET_COMMIT" "$LATEST_COMMIT" -- '*.ts' '*.tsx' '*.js' '*.jsx')
|
28
|
-
fi
|
29
|
-
|
30
|
-
if [ -z "$DIFF_FILES" ]; then
|
31
|
-
echo "✅ No matching file changes detected, skipping ESLint check"
|
32
|
-
exit 0
|
33
|
-
fi
|
34
|
-
|
35
|
-
echo "📂 Changed files:"
|
36
|
-
echo "$DIFF_FILES"
|
37
|
-
|
38
|
-
FILE_COUNT=$(echo "$DIFF_FILES" | wc -l)
|
39
|
-
echo "🧾 Total changed files: $FILE_COUNT"
|
40
|
-
|
41
|
-
ESLINT_CONFIG_FILE="$PROJECT_ROOT/.eslintrc.build.cjs"
|
42
|
-
|
43
|
-
ESLINT_CMD_ARGS="--no-error-on-unmatched-pattern --report-unused-disable-directives"
|
44
|
-
|
45
|
-
if [ -f "$ESLINT_CONFIG_FILE" ]; then
|
46
|
-
echo "🔧 Using ESLint config file: $ESLINT_CONFIG_FILE"
|
47
|
-
ESLINT_CMD_ARGS="--config $ESLINT_CONFIG_FILE $ESLINT_CMD_ARGS"
|
48
|
-
else
|
49
|
-
echo "⚠️ ESLint config file not found, using default ESLint config resolution."
|
50
|
-
fi
|
51
|
-
|
52
|
-
echo "$DIFF_FILES" | tr -d '\r' | \
|
53
|
-
xargs -d '\n' -P 4 -n 30 npx --no-install eslint $ESLINT_CMD_ARGS
|
54
|
-
|
55
|
-
if [ $? -ne 0 ]; then
|
56
|
-
echo "❌ ESLint check failed. Aborting build process"
|
57
|
-
exit 1
|
58
|
-
fi
|
59
|
-
|
1
|
+
#!/usr/bin/env sh
|
2
|
+
echo "🔍 Starting ESLint check (Git diff files only)..."
|
3
|
+
|
4
|
+
# 切换到 Git 仓库根目录
|
5
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
6
|
+
cd "$PROJECT_ROOT" || exit 1
|
7
|
+
|
8
|
+
# 参数:commitId(必填),路径(可选)
|
9
|
+
TARGET_COMMIT=$1
|
10
|
+
LATEST_COMMIT=$(git rev-parse HEAD)
|
11
|
+
|
12
|
+
if [ -z "$TARGET_COMMIT" ]; then
|
13
|
+
echo "❗ Error: Missing target commit ID."
|
14
|
+
echo "👉 Usage: $0 <target-commit-id> [project-path]"
|
15
|
+
exit 1
|
16
|
+
fi
|
17
|
+
|
18
|
+
echo "获取到上一次运行commit ID: $TARGET_COMMIT"
|
19
|
+
echo "获取到当前最新的commit ID: $LATEST_COMMIT"
|
20
|
+
|
21
|
+
# 处理路径参数
|
22
|
+
if [ -n "$FULL_PATH" ]; then
|
23
|
+
PROJECT_NAME=$(basename "$FULL_PATH")
|
24
|
+
echo "📂 检测子项目: $PROJECT_NAME"
|
25
|
+
DIFF_FILES=$(git diff --name-only "$TARGET_COMMIT" "$LATEST_COMMIT" -- "*/$PROJECT_NAME/*.{ts,tsx,js,jsx}")
|
26
|
+
else
|
27
|
+
DIFF_FILES=$(git diff --name-only "$TARGET_COMMIT" "$LATEST_COMMIT" -- '*.ts' '*.tsx' '*.js' '*.jsx')
|
28
|
+
fi
|
29
|
+
|
30
|
+
if [ -z "$DIFF_FILES" ]; then
|
31
|
+
echo "✅ No matching file changes detected, skipping ESLint check"
|
32
|
+
exit 0
|
33
|
+
fi
|
34
|
+
|
35
|
+
echo "📂 Changed files:"
|
36
|
+
echo "$DIFF_FILES"
|
37
|
+
|
38
|
+
FILE_COUNT=$(echo "$DIFF_FILES" | wc -l)
|
39
|
+
echo "🧾 Total changed files: $FILE_COUNT"
|
40
|
+
|
41
|
+
ESLINT_CONFIG_FILE="$PROJECT_ROOT/.eslintrc.build.cjs"
|
42
|
+
|
43
|
+
ESLINT_CMD_ARGS="--no-error-on-unmatched-pattern --report-unused-disable-directives"
|
44
|
+
|
45
|
+
if [ -f "$ESLINT_CONFIG_FILE" ]; then
|
46
|
+
echo "🔧 Using ESLint config file: $ESLINT_CONFIG_FILE"
|
47
|
+
ESLINT_CMD_ARGS="--config $ESLINT_CONFIG_FILE $ESLINT_CMD_ARGS"
|
48
|
+
else
|
49
|
+
echo "⚠️ ESLint config file not found, using default ESLint config resolution."
|
50
|
+
fi
|
51
|
+
|
52
|
+
echo "$DIFF_FILES" | tr -d '\r' | \
|
53
|
+
xargs -d '\n' -P 4 -n 30 npx --no-install eslint $ESLINT_CMD_ARGS
|
54
|
+
|
55
|
+
if [ $? -ne 0 ]; then
|
56
|
+
echo "❌ ESLint check failed. Aborting build process"
|
57
|
+
exit 1
|
58
|
+
fi
|
59
|
+
|
60
60
|
echo "✅ ESLint check passed"
|
package/scripts/initConfigs.js
CHANGED
@@ -1,98 +1,121 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
|
3
|
-
const fs = require('fs');
|
4
|
-
const path = require('path');
|
5
|
-
|
6
|
-
function fileExists(filepath) {
|
7
|
-
try {
|
8
|
-
return fs.existsSync(filepath);
|
9
|
-
} catch (err) {
|
10
|
-
console.error(`❌ Check whether there are any errors in the file: ${filepath}`, err);
|
11
|
-
return false;
|
12
|
-
}
|
13
|
-
}
|
14
|
-
|
15
|
-
function createIfNotExists(filename, content) {
|
16
|
-
const filepath = path.resolve(process.cwd(), filename);
|
17
|
-
try {
|
18
|
-
if (!fs.existsSync(filepath)) {
|
19
|
-
fs.writeFileSync(filepath, content, { encoding: 'utf-8' });
|
20
|
-
console.log(`✅ The ${filename} has been created`);
|
21
|
-
}
|
22
|
-
} catch (err) {
|
23
|
-
console.error(`❌ Failed to create the file: ${filename}`, err);
|
24
|
-
}
|
25
|
-
}
|
26
|
-
|
27
|
-
function hasAnyFileExist(files) {
|
28
|
-
const cwd = process.cwd();
|
29
|
-
return files.some((file) => fileExists(path.join(cwd, file)));
|
30
|
-
}
|
31
|
-
|
32
|
-
function initConfigs() {
|
33
|
-
const
|
34
|
-
|
35
|
-
|
36
|
-
'.
|
37
|
-
'.
|
38
|
-
'.
|
39
|
-
'.
|
40
|
-
'
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
'.
|
47
|
-
'.
|
48
|
-
'.
|
49
|
-
'.
|
50
|
-
'
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
const fs = require('node:fs');
|
4
|
+
const path = require('node:path');
|
5
|
+
|
6
|
+
function fileExists(filepath) {
|
7
|
+
try {
|
8
|
+
return fs.existsSync(filepath);
|
9
|
+
} catch (err) {
|
10
|
+
console.error(`❌ Check whether there are any errors in the file: ${filepath}`, err);
|
11
|
+
return false;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
function createIfNotExists(filename, content) {
|
16
|
+
const filepath = path.resolve(process.cwd(), filename);
|
17
|
+
try {
|
18
|
+
if (!fs.existsSync(filepath)) {
|
19
|
+
fs.writeFileSync(filepath, content, { encoding: 'utf-8' });
|
20
|
+
console.log(`✅ The ${filename} has been created`);
|
21
|
+
}
|
22
|
+
} catch (err) {
|
23
|
+
console.error(`❌ Failed to create the file: ${filename}`, err);
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
function hasAnyFileExist(files) {
|
28
|
+
const cwd = process.cwd();
|
29
|
+
return files.some((file) => fileExists(path.join(cwd, file)));
|
30
|
+
}
|
31
|
+
|
32
|
+
function initConfigs() {
|
33
|
+
const biomeConfigFiles = ['biome.json', 'biome.jsonc'];
|
34
|
+
|
35
|
+
const stylelintConfigFiles = [
|
36
|
+
'.stylelintrc.js',
|
37
|
+
'.stylelintrc.cjs',
|
38
|
+
'.stylelintrc.json',
|
39
|
+
'.stylelintrc.yaml',
|
40
|
+
'.stylelintrc.yml',
|
41
|
+
'.stylelintrc',
|
42
|
+
'stylelint.config.js',
|
43
|
+
];
|
44
|
+
|
45
|
+
const prettierConfigFiles = [
|
46
|
+
'.prettierrc',
|
47
|
+
'.prettierrc.js',
|
48
|
+
'.prettierrc.cjs',
|
49
|
+
'.prettierrc.json',
|
50
|
+
'.prettierrc.yaml',
|
51
|
+
'.prettierrc.yml',
|
52
|
+
'prettier.config.js',
|
53
|
+
];
|
54
|
+
|
55
|
+
try {
|
56
|
+
// 创建 biome.jsonc 配置(替代 ESLint 和 Prettier)
|
57
|
+
if (!hasAnyFileExist(biomeConfigFiles)) {
|
58
|
+
const biomeContent = `{
|
59
|
+
"$schema": "https://biomejs.dev/schemas/2.2.6/schema.json",
|
60
|
+
"extends": ["@apdesign/code-style-react/biome.jsonc"],
|
61
|
+
"linter": {
|
62
|
+
"rules": {
|
63
|
+
// 在这里添加你的自定义规则
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}`;
|
67
|
+
createIfNotExists('biome.jsonc', biomeContent);
|
68
|
+
}
|
69
|
+
|
70
|
+
// 创建 Stylelint 配置
|
71
|
+
if (!hasAnyFileExist(stylelintConfigFiles)) {
|
72
|
+
const stylelintContent = `const baseConfig = require('@apdesign/code-style-react/stylelint/.stylelintrc.js');
|
73
|
+
module.exports = {
|
74
|
+
...baseConfig,
|
75
|
+
rules: {
|
76
|
+
...baseConfig.rules,
|
77
|
+
},
|
78
|
+
};`;
|
79
|
+
createIfNotExists('.stylelintrc.cjs', stylelintContent);
|
80
|
+
}
|
81
|
+
|
82
|
+
// 创建 Prettier 配置(向后兼容)
|
83
|
+
if (!hasAnyFileExist(prettierConfigFiles)) {
|
84
|
+
const prettierContent = `const baseConfig = require('@apdesign/code-style-react/.prettierrc.js');
|
85
|
+
module.exports = {
|
86
|
+
...baseConfig
|
87
|
+
};`;
|
88
|
+
createIfNotExists('.prettierrc.cjs', prettierContent);
|
89
|
+
}
|
90
|
+
|
91
|
+
// 创建 lefthook 配置
|
92
|
+
const lefthookConfigPath = path.resolve(process.cwd(), 'lefthook.yml');
|
93
|
+
if (!fs.existsSync(lefthookConfigPath)) {
|
94
|
+
const lefthookContent = `pre-commit:
|
95
|
+
parallel: true
|
96
|
+
commands:
|
97
|
+
lint:
|
98
|
+
glob: "*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}"
|
99
|
+
run: npx lint-staged
|
100
|
+
`;
|
101
|
+
createIfNotExists('lefthook.yml', lefthookContent);
|
102
|
+
}
|
103
|
+
|
104
|
+
// 创建 lint-staged 配置(如果 package.json 中没有)
|
105
|
+
const packageJsonPath = path.resolve(process.cwd(), 'package.json');
|
106
|
+
if (fs.existsSync(packageJsonPath)) {
|
107
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
108
|
+
if (!packageJson['lint-staged']) {
|
109
|
+
packageJson['lint-staged'] = {
|
110
|
+
'*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}': ['npx ultracite fix'],
|
111
|
+
};
|
112
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf-8');
|
113
|
+
console.log('✅ lint-staged configuration added to package.json');
|
114
|
+
}
|
115
|
+
}
|
116
|
+
} catch (err) {
|
117
|
+
console.error('❌ Failed to initialize configuration:', err);
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
module.exports = initConfigs;
|