@apdesign/code-style-react 1.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.
@@ -0,0 +1,91 @@
1
+ module.exports = {
2
+ root: true,
3
+ env: {
4
+ browser: true,
5
+ node: true,
6
+ es2021: true,
7
+ },
8
+ parser: '@typescript-eslint/parser',
9
+ extends: [
10
+ 'airbnb',
11
+ 'airbnb/hooks',
12
+ 'plugin:@typescript-eslint/recommended',
13
+ 'plugin:import/errors',
14
+ 'plugin:import/warnings',
15
+ 'prettier',
16
+ ],
17
+ plugins: ['@typescript-eslint', 'import', 'jsx-a11y', 'react', 'react-hooks'],
18
+ rules: {
19
+ 'arrow-body-style': 'off',
20
+
21
+ camelcase: 'off',
22
+ 'class-methods-use-this': 'off',
23
+
24
+ 'import/first': 'off',
25
+ 'import/extensions': 'off',
26
+ 'import/prefer-default-export': 'off',
27
+
28
+ 'jsx-a11y/click-events-have-key-events': 'off',
29
+ 'jsx-a11y/no-static-element-interactions': 'off',
30
+ 'jsx-a11y/no-noninteractive-element-interactions': 'off',
31
+
32
+ 'linebreak-style': 'off',
33
+
34
+ 'max-classes-per-file': 'off',
35
+
36
+ 'no-undef': 'off',
37
+ 'no-plusplus': 'off',
38
+
39
+ 'react/function-component-definition': 'off',
40
+ 'react-hooks/exhaustive-deps': 'off',
41
+ 'react/prop-types': 'off',
42
+ 'react/react-in-jsx-scope': 'off',
43
+ 'react/require-default-props': 'off',
44
+ 'react/jsx-boolean-value': 'off',
45
+ 'react/jsx-filename-extension': 'off',
46
+ 'react/jsx-props-no-spreading': 'off',
47
+ 'react/self-closing-comp': 'off',
48
+ 'react/jsx-no-useless-fragment': 'off',
49
+
50
+ 'no-unused-vars': 'off',
51
+ '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
52
+
53
+ 'no-useless-constructor': 'off',
54
+ '@typescript-eslint/no-useless-constructor': 'warn',
55
+
56
+ 'no-shadow': 'off',
57
+ '@typescript-eslint/no-shadow': 'warn',
58
+
59
+ 'no-empty-function': ['warn', { allow: ['constructors'] }],
60
+ 'no-param-reassign': ['warn', { props: true, ignorePropertyModificationsFor: ['draft'] }],
61
+ 'no-restricted-syntax': [
62
+ 'warn',
63
+ {
64
+ selector: "CallExpression[callee.name='useMemo']",
65
+ message: 'Avoid using useMemo unless caching a computed value improves performance.',
66
+ },
67
+ {
68
+ selector: "CallExpression[callee.name='useCallback']",
69
+ message:
70
+ 'Avoid using useCallback unless you need to cache a function to prevent unnecessary re-renders.',
71
+ },
72
+ ],
73
+ },
74
+ parserOptions: {
75
+ sourceType: 'module',
76
+ },
77
+ ignorePatterns: ['dist/', 'node_modules/', '*.d.ts', 'mock', '.eslintrc.cjs'],
78
+ settings: {
79
+ react: {
80
+ version: 'detect',
81
+ },
82
+ 'import/resolver': {
83
+ alias: {
84
+ map: [
85
+ ['@', './src'], // 将 '@' 映射到 'src' 目录
86
+ ],
87
+ extensions: ['.ts', '.tsx', '.js', '.jsx', '.d.ts'],
88
+ },
89
+ },
90
+ },
91
+ };
package/.eslintrc.js ADDED
@@ -0,0 +1,91 @@
1
+ module.exports = {
2
+ root: true,
3
+ env: {
4
+ browser: true,
5
+ node: true,
6
+ es2021: true,
7
+ },
8
+ parser: '@typescript-eslint/parser',
9
+ extends: [
10
+ 'airbnb',
11
+ 'airbnb/hooks',
12
+ 'plugin:@typescript-eslint/recommended',
13
+ 'plugin:import/errors',
14
+ 'plugin:import/warnings',
15
+ 'prettier',
16
+ ],
17
+ plugins: ['@typescript-eslint', 'import', 'jsx-a11y', 'react', 'react-hooks'],
18
+ rules: {
19
+ 'arrow-body-style': 'off',
20
+
21
+ camelcase: 'off',
22
+ 'class-methods-use-this': 'off',
23
+
24
+ 'import/first': 'off',
25
+ 'import/extensions': 'off',
26
+ 'import/prefer-default-export': 'off',
27
+
28
+ 'jsx-a11y/click-events-have-key-events': 'off',
29
+ 'jsx-a11y/no-static-element-interactions': 'off',
30
+ 'jsx-a11y/no-noninteractive-element-interactions': 'off',
31
+
32
+ 'linebreak-style': 'off',
33
+
34
+ 'max-classes-per-file': 'off',
35
+
36
+ 'no-undef': 'off',
37
+ 'no-plusplus': 'off',
38
+
39
+ 'react/function-component-definition': 'off',
40
+ 'react-hooks/exhaustive-deps': 'off',
41
+ 'react/prop-types': 'off',
42
+ 'react/react-in-jsx-scope': 'off',
43
+ 'react/require-default-props': 'off',
44
+ 'react/jsx-boolean-value': 'off',
45
+ 'react/jsx-filename-extension': 'off',
46
+ 'react/jsx-props-no-spreading': 'off',
47
+ 'react/self-closing-comp': 'off',
48
+ 'react/jsx-no-useless-fragment': 'off',
49
+
50
+ 'no-unused-vars': 'off',
51
+ '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
52
+
53
+ 'no-useless-constructor': 'off',
54
+ '@typescript-eslint/no-useless-constructor': 'error',
55
+
56
+ 'no-shadow': 'off',
57
+ '@typescript-eslint/no-shadow': 'error',
58
+
59
+ 'no-empty-function': ['error', { allow: ['constructors'] }],
60
+ 'no-param-reassign': ['error', { props: true, ignorePropertyModificationsFor: ['draft'] }],
61
+ 'no-restricted-syntax': [
62
+ 'warn',
63
+ {
64
+ selector: "CallExpression[callee.name='useMemo']",
65
+ message: 'Avoid using useMemo unless caching a computed value improves performance.',
66
+ },
67
+ {
68
+ selector: "CallExpression[callee.name='useCallback']",
69
+ message:
70
+ 'Avoid using useCallback unless you need to cache a function to prevent unnecessary re-renders.',
71
+ },
72
+ ],
73
+ },
74
+ parserOptions: {
75
+ sourceType: 'module',
76
+ },
77
+ ignorePatterns: ['dist/', 'node_modules/', '*.d.ts', 'mock', '.eslintrc.cjs'],
78
+ settings: {
79
+ react: {
80
+ version: 'detect',
81
+ },
82
+ 'import/resolver': {
83
+ alias: {
84
+ map: [
85
+ ['@', './src'], // 将 '@' 映射到 'src' 目录
86
+ ],
87
+ extensions: ['.ts', '.tsx', '.js', '.jsx', '.d.ts'],
88
+ },
89
+ },
90
+ },
91
+ };
package/.prettierrc.js ADDED
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ useTabs: false,
3
+ tabWidth: 2,
4
+ printWidth: 100,
5
+ singleQuote: true,
6
+ trailingComma: 'all',
7
+ bracketSpacing: true,
8
+ semi: true,
9
+ embeddedLanguageFormatting: 'auto',
10
+ jsxSingleQuote: true,
11
+ };
@@ -0,0 +1,23 @@
1
+ module.exports = {
2
+ extends: ['stylelint-config-standard'],
3
+ plugins: ['stylelint-less', 'stylelint-scss'],
4
+ overrides: [
5
+ {
6
+ files: ['**/*.less'],
7
+ customSyntax: 'postcss-less',
8
+ },
9
+ {
10
+ files: ['**/*.scss', '**/*.sass'],
11
+ customSyntax: 'postcss-less',
12
+ },
13
+ ],
14
+ rules: {
15
+ 'selector-class-pattern': '^[a-z][a-zA-Z0-9-]*$',
16
+ 'selector-pseudo-class-no-unknown': [
17
+ true,
18
+ {
19
+ ignorePseudoClasses: ['global'],
20
+ },
21
+ ],
22
+ },
23
+ };
package/README.md ADDED
File without changes
package/husky/_/h ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env sh
2
+ [ "$HUSKY" = "2" ] && set -x
3
+ n=$(basename "$0")
4
+ s=$(dirname "$(dirname "$0")")/$n
5
+
6
+ if [[ "$(uname)" == "Darwin" ]]; then
7
+ elif [[ "$(uname -o)" == "Msys" || "$(uname)" == "CYGWIN" || "$(uname)" == "MINGW"* ]]; then
8
+ sed -i 's/\r//' "$0"
9
+ fi
10
+
11
+ [ ! -f "$s" ] && exit 0
12
+
13
+ if [ -f "$HOME/.huskyrc" ]; then
14
+ echo "husky - '~/.huskyrc' is DEPRECATED, please move your code to ~/.config/husky/init.sh"
15
+ fi
16
+ i="${XDG_CONFIG_HOME:-$HOME/.config}/husky/init.sh"
17
+ [ -f "$i" ] && . "$i"
18
+
19
+ [ "${HUSKY-}" = "0" ] && exit 0
20
+
21
+ export PATH="node_modules/.bin:$PATH"
22
+ sh -e "$s" "$@"
23
+ c=$?
24
+
25
+ [ $c != 0 ] && echo "husky - $n script failed (code $c)"
26
+ [ $c = 127 ] && echo "husky - command not found in PATH=$PATH"
27
+ exit $c
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env sh
2
+ . "$(dirname "$0")/h"
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env sh
2
+ . "$(dirname "$0")/h"
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env sh
2
+ npx lint-staged
package/husky/pre-push ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env sh
2
+ branch_name=$(git symbolic-ref --short HEAD)
3
+
4
+ branch_regex_master="^master$"
5
+ branch_regex_env="^(master|uat|dev)-[a-z]+$"
6
+ branch_regex_feature="^(feature|test|hotfix)-[a-z]+-[a-zA-Z0-9]+(-[A-Z]+[0-9]+)?$"
7
+ branch_regex_release="^release-[a-z]+-[0-9]{8}$"
8
+
9
+ if echo "$branch_name" | grep -Eq "$branch_regex_master"; then
10
+ exit 0
11
+ elif echo "$branch_name" | grep -Eq "$branch_regex_env"; then
12
+ exit 0
13
+ elif echo "$branch_name" | grep -Eq "$branch_regex_feature"; then
14
+ exit 0
15
+ elif echo "$branch_name" | grep -Eq "$branch_regex_release"; then
16
+ exit 0
17
+ else
18
+ echo -e "❌ \033[31m[ERROR] 当前分支名 '$branch_name' 不符合规范!\033[0m"
19
+ echo "分支命名规范要求如下:"
20
+ echo "✅ master"
21
+ echo "✅ master|uat|dev-[小写字母]"
22
+ echo "✅ feature|test|hotfix-[小写字母]+-[字母或数字]+(可选 -大写字母+数字)"
23
+ echo "✅ release-[小写字母]+-8位日期"
24
+ exit 1
25
+ fi
package/index.js ADDED
@@ -0,0 +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
+ main();
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@apdesign/code-style-react",
3
+ "version": "1.0.0",
4
+ "scripts": {},
5
+ "files": [
6
+ "index.js",
7
+ ".prettierrc.js",
8
+ ".eslintrc.js",
9
+ ".eslintrc.build.js",
10
+ ".stylelintrc.js",
11
+ "husky",
12
+ "scripts"
13
+ ],
14
+ "keywords": [],
15
+ "author": "",
16
+ "license": "ISC",
17
+ "description": "",
18
+ "dependencies": {
19
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
20
+ "@typescript-eslint/parser": "^6.21.0",
21
+ "eslint": "^8.57.1",
22
+ "eslint-config-airbnb": "^19.0.4",
23
+ "eslint-config-prettier": "^9.1.0",
24
+ "eslint-import-resolver-alias": "^1.1.2",
25
+ "eslint-plugin-import": "^2.31.0",
26
+ "eslint-plugin-jsx-a11y": "^6.10.2",
27
+ "eslint-plugin-prettier": "^5.2.1",
28
+ "eslint-plugin-react": "^7.37.2",
29
+ "eslint-plugin-react-hooks": "^4.6.2",
30
+ "husky": "^9.1.7",
31
+ "lint-staged": "^15.3.0",
32
+ "postcss-less": "^6.0.0",
33
+ "prettier": "^3.3.3",
34
+ "stylelint": "^16.19.1",
35
+ "stylelint-config-standard": "^38.0.0",
36
+ "stylelint-less": "^3.0.1",
37
+ "stylelint-scss": "^6.12.0"
38
+ }
39
+ }
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env sh
2
+ echo "🔍 Starting ESLint check (Git diff files only)..."
3
+
4
+ DIFF_FILES=$(git diff --name-only origin/master...HEAD -- '*.ts' '*.tsx' '*.js' '*.jsx')
5
+
6
+ if [ -z "$DIFF_FILES" ]; then
7
+ echo "✅ No matching file changes detected, skipping ESLint check"
8
+ exit 0
9
+ fi
10
+
11
+ echo "📂 Changed files:"
12
+ echo "$DIFF_FILES"
13
+
14
+ npx eslint --config .eslintrc.build.cjs $DIFF_FILES \
15
+ --no-error-on-unmatched-pattern \
16
+ --report-unused-disable-directives
17
+
18
+ if [ $? -ne 0 ]; then
19
+ echo "❌ ESLint check failed. Aborting build process"
20
+ exit 1
21
+ fi
22
+
23
+ echo "✅ ESLint check passed"
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env sh
2
+ echo "🔍 Starting Stylelint check (Git diff files only)..."
3
+
4
+ DIFF_FILES=$(git diff --name-only origin/master...HEAD -- '*.css' '*.scss' '*.sass' '*.less')
5
+
6
+ if [ -z "$DIFF_FILES" ]; then
7
+ echo "✅ No style file changes detected, skipping Stylelint check"
8
+ exit 0
9
+ fi
10
+
11
+ echo "📂 Changed files:"
12
+ echo "$DIFF_FILES"
13
+
14
+ npx stylelint $DIFF_FILES \
15
+ --allow-empty-input \
16
+ --report-needless-disables \
17
+ --report-invalid-scope-disables
18
+
19
+ if [ $? -ne 0 ]; then
20
+ echo "❌ Stylelint check failed. Aborting build process"
21
+ exit 1
22
+ fi
23
+
24
+ echo "✅ Stylelint check passed"
@@ -0,0 +1,98 @@
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 eslintConfigFiles = [
34
+ '.eslintrc.js',
35
+ '.eslintrc.cjs',
36
+ '.eslintrc.json',
37
+ '.eslintrc.yaml',
38
+ '.eslintrc.yml',
39
+ '.eslintrc',
40
+ 'eslint.config.js',
41
+ ];
42
+
43
+ const stylelintConfigFiles = [
44
+ '.stylelintrc.js',
45
+ '.stylelintrc.cjs',
46
+ '.stylelintrc.json',
47
+ '.stylelintrc.yaml',
48
+ '.stylelintrc.yml',
49
+ '.stylelintrc',
50
+ 'stylelint.config.js',
51
+ ];
52
+
53
+ const prettierConfigFiles = [
54
+ '.prettierrc',
55
+ '.prettierrc.js',
56
+ '.prettierrc.cjs',
57
+ '.prettierrc.json',
58
+ '.prettierrc.yaml',
59
+ '.prettierrc.yml',
60
+ 'prettier.config.js',
61
+ ];
62
+
63
+ try {
64
+ if (!hasAnyFileExist(eslintConfigFiles)) {
65
+ const eslintContent = `const baseConfig = require('@apdesign/rule-react/.eslintrc.js');
66
+ module.exports = {
67
+ ...baseConfig,
68
+ rules: {
69
+ ...baseConfig.rules,
70
+ },
71
+ };`;
72
+ createIfNotExists('.eslintrc.cjs', eslintContent);
73
+ }
74
+
75
+ if (!hasAnyFileExist(stylelintConfigFiles)) {
76
+ const stylelintContent = `const baseConfig = require('@apdesign/rule-react/.stylelintrc.js');
77
+ module.exports = {
78
+ ...baseConfig,
79
+ rules: {
80
+ ...baseConfig.rules,
81
+ },
82
+ };`;
83
+ createIfNotExists('.stylelintrc.cjs', stylelintContent);
84
+ }
85
+
86
+ if (!hasAnyFileExist(prettierConfigFiles)) {
87
+ const prettierContent = `const baseConfig = require('@apdesign/rule-react/.prettierrc.js');
88
+ module.exports = {
89
+ ...baseConfig
90
+ };`;
91
+ createIfNotExists('.prettierrc.cjs', prettierContent);
92
+ }
93
+ } catch (err) {
94
+ console.error('❌ Failed to initialize configuration:', err);
95
+ }
96
+ }
97
+
98
+ module.exports = initConfigs;
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync } = require('child_process');
6
+
7
+ function initHusky() {
8
+ const projectRoot = process.cwd();
9
+ const huskyTarget = path.join(projectRoot, '.husky');
10
+ const huskySource = path.join(__dirname, '../husky');
11
+
12
+ try {
13
+ if (fs.existsSync(huskyTarget)) {
14
+ fs.rmSync(huskyTarget, { recursive: true, force: true });
15
+ }
16
+ fs.cpSync(huskySource, huskyTarget, { recursive: true });
17
+
18
+ fs.readdirSync(huskyTarget).forEach((file) => {
19
+ const filePath = path.join(huskyTarget, file);
20
+ if (fs.statSync(filePath).isFile()) {
21
+ fs.chmodSync(filePath, 0o755);
22
+ }
23
+ });
24
+
25
+ execSync('git config core.hooksPath .husky');
26
+
27
+ console.log('✅ Husky hooks installed from @apdesign/rule-react');
28
+ } catch (err) {
29
+ console.error('❌ Failed to initialize husky:', err);
30
+ }
31
+ }
32
+
33
+ module.exports = initHusky;
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ function initScripts() {
7
+ const projectRoot = process.cwd();
8
+ const projectScriptsDir = path.join(projectRoot, 'scripts');
9
+ const packageScriptsDir = path.join(__dirname, '../scripts');
10
+
11
+ try {
12
+ if (!fs.existsSync(projectScriptsDir)) {
13
+ fs.mkdirSync(projectScriptsDir, { recursive: true });
14
+ console.log('📁 Created scripts directory in project');
15
+ }
16
+
17
+ fs.readdirSync(packageScriptsDir)
18
+ .filter((file) => file.endsWith('.sh'))
19
+ .forEach((file) => {
20
+ const srcFile = path.join(packageScriptsDir, file);
21
+ const destFile = path.join(projectScriptsDir, file);
22
+
23
+ if (fs.existsSync(destFile)) {
24
+ return;
25
+ }
26
+
27
+ fs.copyFileSync(srcFile, destFile);
28
+ fs.chmodSync(destFile, 0o755);
29
+ console.log(`📄 Copied ${file} to scripts/`);
30
+ });
31
+ } catch (err) {
32
+ console.error('❌ Failed to initialize scripts:', err);
33
+ }
34
+ }
35
+
36
+ module.exports = initScripts;