@apdesign/code-style-react 1.0.4 → 1.0.5

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 CHANGED
@@ -7,5 +7,4 @@ module.exports = {
7
7
  bracketSpacing: true,
8
8
  semi: true,
9
9
  embeddedLanguageFormatting: 'auto',
10
- jsxSingleQuote: true,
11
10
  };
package/cli.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ const main = require('./index');
4
+
5
+ const args = process.argv.slice(2);
6
+
7
+ if (args[0] === 'init') {
8
+ main();
9
+ } else {
10
+ console.log('Usage: apdesign-code-style init');
11
+ }
package/index.js CHANGED
@@ -10,4 +10,4 @@ function main() {
10
10
  initConfigs();
11
11
  }
12
12
 
13
- main();
13
+ module.exports = main;
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@apdesign/code-style-react",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "scripts": {},
5
+ "bin": {
6
+ "apdesign-code-style": "cli.js"
7
+ },
5
8
  "files": [
6
9
  "index.js",
7
10
  ".prettierrc.js",
8
- ".eslintrc.js",
9
- ".eslintrc.build.js",
10
- ".stylelintrc.js",
11
+ "eslint",
12
+ "stylelint",
11
13
  "husky",
12
14
  "scripts"
13
15
  ],
@@ -62,7 +62,7 @@ function initConfigs() {
62
62
 
63
63
  try {
64
64
  if (!hasAnyFileExist(eslintConfigFiles)) {
65
- const eslintContent = `const baseConfig = require('@apdesign/code-style-react/.eslintrc.js');
65
+ const eslintContent = `const baseConfig = require('@apdesign/code-style-react/eslint/.eslintrc.js');
66
66
  module.exports = {
67
67
  ...baseConfig,
68
68
  rules: {
@@ -73,7 +73,7 @@ module.exports = {
73
73
  }
74
74
 
75
75
  if (!hasAnyFileExist(stylelintConfigFiles)) {
76
- const stylelintContent = `const baseConfig = require('@apdesign/code-style-react/.stylelintrc.js');
76
+ const stylelintContent = `const baseConfig = require('@apdesign/code-style-react/stylelint/.stylelintrc.js');
77
77
  module.exports = {
78
78
  ...baseConfig,
79
79
  rules: {
@@ -1,6 +1,16 @@
1
+ const colorMustUseVariable = require('./rules/color-must-use-variable');
2
+
1
3
  module.exports = {
2
4
  extends: ['stylelint-config-standard'],
3
- plugins: ['stylelint-less', 'stylelint-scss'],
5
+ plugins: [
6
+ 'stylelint-less',
7
+ 'stylelint-scss',
8
+ {
9
+ rules: {
10
+ [colorMustUseVariable.ruleName]: colorMustUseVariable,
11
+ },
12
+ },
13
+ ],
4
14
  overrides: [
5
15
  {
6
16
  files: ['**/*.less'],
@@ -8,7 +18,7 @@ module.exports = {
8
18
  },
9
19
  {
10
20
  files: ['**/*.scss', '**/*.sass'],
11
- customSyntax: 'postcss-less',
21
+ customSyntax: 'postcss-scss',
12
22
  },
13
23
  ],
14
24
  rules: {
@@ -22,5 +32,12 @@ module.exports = {
22
32
 
23
33
  'media-feature-range-notation': null,
24
34
  'property-no-vendor-prefix': null,
35
+
36
+ 'custom/color-must-use-variable': [
37
+ true,
38
+ {
39
+ severity: 'warning',
40
+ },
41
+ ],
25
42
  },
26
43
  };
@@ -0,0 +1,124 @@
1
+ const stylelint = require('stylelint');
2
+ const valueParser = require('postcss-value-parser');
3
+
4
+ const ruleName = 'custom/color-must-use-variable';
5
+ const messages = stylelint.utils.ruleMessages(ruleName, {
6
+ expected: (val) => `Expected color "${val}" to be a color variable`,
7
+ });
8
+
9
+ // 默认颜色关键字
10
+ const defaultCssColorKeywords = [
11
+ 'red',
12
+ 'blue',
13
+ 'green',
14
+ 'black',
15
+ 'white',
16
+ 'gray',
17
+ 'aqua',
18
+ 'fuchsia',
19
+ 'lime',
20
+ 'maroon',
21
+ 'navy',
22
+ 'olive',
23
+ 'purple',
24
+ 'silver',
25
+ 'teal',
26
+ 'yellow',
27
+ 'orange',
28
+ 'pink',
29
+ 'brown',
30
+ 'cyan',
31
+ 'magenta',
32
+ 'gold',
33
+ 'azure',
34
+ ];
35
+
36
+ // 默认检查的属性
37
+ const defaultPropsToCheck = [
38
+ 'color',
39
+ 'background',
40
+ 'background-color',
41
+ 'border',
42
+ 'border-color',
43
+ 'border-top-color',
44
+ 'border-right-color',
45
+ 'border-bottom-color',
46
+ 'border-left-color',
47
+ 'outline',
48
+ 'outline-color',
49
+ 'text-decoration-color',
50
+ 'box-shadow',
51
+ 'text-shadow',
52
+ 'column-rule-color',
53
+ 'caret-color',
54
+ 'fill',
55
+ 'stroke',
56
+ 'stop-color',
57
+ ];
58
+
59
+ const containsVarFunction = (node) => {
60
+ if (node.type === 'function' && node.value === 'var') return true;
61
+ if (node.nodes && node.nodes.length) {
62
+ return node.nodes.some(containsVarFunction);
63
+ }
64
+ return false;
65
+ };
66
+
67
+ module.exports = stylelint.createPlugin(ruleName, (primaryOption, secondaryOptions = {}) => {
68
+ // 合并自定义颜色关键字和默认颜色关键字(去重)
69
+ const cssColorKeywords = Array.from(
70
+ new Set([...(secondaryOptions.cssColorKeywords || []), ...defaultCssColorKeywords]),
71
+ );
72
+
73
+ // 生成颜色匹配正则
74
+ const colorWordRegex = new RegExp(
75
+ `^(#(?:[0-9a-fA-F]{3,8})|(?:${cssColorKeywords.join('|')}))$`,
76
+ 'i',
77
+ );
78
+
79
+ // 判断是否为硬编码颜色文字,如 #fff 或 red
80
+ const isColorWord = (node) => node.type === 'word' && colorWordRegex.test(node.value);
81
+
82
+ // 判断是否为硬编码颜色函数,如 rgb(), hsl() 等
83
+ const isHardcodedFunctionColor = (node) =>
84
+ node.type === 'function' && /^(rgb|rgba|hsl|hsla|lab|lch)$/i.test(node.value);
85
+
86
+ // 合并自定义属性和默认属性(去重)
87
+ const propsToCheck = Array.from(
88
+ new Set([...(secondaryOptions.properties || []), ...defaultPropsToCheck]),
89
+ );
90
+
91
+ return (root, result) => {
92
+ root.walkDecls((decl) => {
93
+ if (!propsToCheck.includes(decl.prop)) return;
94
+
95
+ let parsedValue;
96
+ try {
97
+ parsedValue = valueParser(decl.value);
98
+ } catch (e) {
99
+ return; // 解析失败跳过
100
+ }
101
+
102
+ parsedValue.walk((node) => {
103
+ const nodeStr = valueParser.stringify(node);
104
+ if (containsVarFunction(node)) return; // 跳过包含 var() 的
105
+
106
+ if (isColorWord(node) || isHardcodedFunctionColor(node)) {
107
+ stylelint.utils.report({
108
+ ruleName,
109
+ result,
110
+ node: decl,
111
+ message: messages.expected(nodeStr),
112
+ word: nodeStr,
113
+ index: decl.value.indexOf(nodeStr),
114
+ endIndex: decl.value.indexOf(nodeStr) + nodeStr.length,
115
+ severity: secondaryOptions.severity || 'error',
116
+ });
117
+ }
118
+ });
119
+ });
120
+ };
121
+ });
122
+
123
+ module.exports.ruleName = ruleName;
124
+ module.exports.messages = messages;
File without changes