@oceanbase/codemod 0.4.16 → 1.0.0-alpha.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.
Files changed (33) hide show
  1. package/README.md +19 -8
  2. package/package.json +3 -3
  3. package/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.input.less +2 -0
  4. package/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.output.less +2 -0
  5. package/transforms/__testfixtures__/less-to-token/case-insensitive.input.less +2 -0
  6. package/transforms/__testfixtures__/less-to-token/case-insensitive.output.less +2 -0
  7. package/transforms/__testfixtures__/less-to-token/mixin.input.less +3 -0
  8. package/transforms/__testfixtures__/less-to-token/mixin.output.less +3 -0
  9. package/transforms/__testfixtures__/less-to-token/obui-less-to-token.input.less +2 -0
  10. package/transforms/__testfixtures__/less-to-token/obui-less-to-token.output.less +2 -0
  11. package/transforms/__testfixtures__/less-to-token/obui-less-token-to-token.input.less +1 -0
  12. package/transforms/__testfixtures__/less-to-token/obui-less-token-to-token.output.less +1 -0
  13. package/transforms/__testfixtures__/style-to-token/antd-style.input.js +3 -0
  14. package/transforms/__testfixtures__/style-to-token/antd-style.output.js +3 -0
  15. package/transforms/__testfixtures__/style-to-token/block-statement.input.js +4 -0
  16. package/transforms/__testfixtures__/style-to-token/block-statement.output.js +4 -0
  17. package/transforms/__testfixtures__/style-to-token/class-component.input.js +2 -2
  18. package/transforms/__testfixtures__/style-to-token/class-component.output.js +2 -2
  19. package/transforms/__testfixtures__/style-to-token/existed-useToken.input.js +2 -2
  20. package/transforms/__testfixtures__/style-to-token/existed-useToken.output.js +2 -2
  21. package/transforms/__testfixtures__/style-to-token/function-component.input.js +4 -4
  22. package/transforms/__testfixtures__/style-to-token/function-component.output.js +4 -4
  23. package/transforms/__testfixtures__/style-to-token/function.input.js +6 -6
  24. package/transforms/__testfixtures__/style-to-token/function.output.js +7 -7
  25. package/transforms/__testfixtures__/style-to-token/hooks.input.js +4 -4
  26. package/transforms/__testfixtures__/style-to-token/hooks.output.js +4 -4
  27. package/transforms/__testfixtures__/style-to-token/nested-block-statement.input.js +3 -3
  28. package/transforms/__testfixtures__/style-to-token/nested-block-statement.output.js +3 -3
  29. package/transforms/__testfixtures__/style-to-token/top-identifier.input.js +1 -0
  30. package/transforms/__testfixtures__/style-to-token/top-identifier.output.js +1 -0
  31. package/transforms/less-to-token.js +16 -6
  32. package/transforms/style-to-token.js +352 -121
  33. package/transforms/utils/token.js +39 -0
package/README.md CHANGED
@@ -181,12 +181,12 @@ transform fixed style to antd v5 design token.
181
181
  + const { token } = theme.useToken();
182
182
  return (
183
183
  - <div>
184
- - <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
185
- - <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4d4f' }}></Button>
184
+ - <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
185
+ - <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4d4f', fontSize: 12 }}></Button>
186
186
  - </div>
187
187
  + <div>
188
- + <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
189
- + <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
188
+ + <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
189
+ + <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
190
190
  + </div>
191
191
  );
192
192
  };
@@ -210,13 +210,13 @@ export default Demo;
210
210
  render() {
211
211
  return (
212
212
  - <div>
213
- - <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '#d9d9d9' }} />
214
- - <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4d4f' }}></Button>
213
+ - <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '#d9d9d9', fontSize: 14 }} />
214
+ - <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4d4f', fontSize: 12 }}></Button>
215
215
  - <div color="#fafafa" border="1px solid #fafafa" />
216
216
  - </div>
217
217
  + <div>
218
- + <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBgLayout}` }} />
219
- + <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
218
+ + <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBgLayout}`, fontSize: token.fontSize }} />
219
+ + <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
220
220
  + <div color={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
221
221
  + </div>
222
222
  );
@@ -240,11 +240,13 @@ export default Demo;
240
240
  - warning: '#faad14',
241
241
  - error: '#ff4d4f',
242
242
  - border: '1px solid #d9d9d9',
243
+ - fontSize: 14,
243
244
  + info: token.colorInfo,
244
245
  + success: token.colorSuccess,
245
246
  + warning: token.colorWarning,
246
247
  + error: token.colorError,
247
248
  + border: `1px solid ${token.colorBorder}`,
249
+ + fontSize: token.fontSize,
248
250
  };
249
251
 
250
252
  function getColorList() {
@@ -274,6 +276,11 @@ export default Demo;
274
276
  - color: '1px solid #d9d9d9',
275
277
  + color: `1px solid ${token.colorBorder}`,
276
278
  },
279
+ {
280
+ type: 'fontSize',
281
+ - fontSize: 14,
282
+ + fontSize: token.fontSize,
283
+ }
277
284
  ];
278
285
  }
279
286
  ```
@@ -289,19 +296,23 @@ transform fixed less style to antd v5 design token.
289
296
  - background: #52c41a;
290
297
  - background-color: #faad14;
291
298
  - border-color: #ff4d4f;
299
+ - font-size: 14px;
292
300
  + color: @colorInfo;
293
301
  + background: @colorSuccess;
294
302
  + background-color: @colorWarning;
295
303
  + border-color: @colorError;
304
+ + font-size: @fontSize;
296
305
  .content {
297
306
  - color: rgba(0, 0, 0, 0.85);
298
307
  - background: rgba(0, 0, 0,0.65);
299
308
  - background-color: rgba(0,0,0,0.45);
300
309
  - border: 1px solid #d9d9d9;
310
+ - font-size: 12px;
301
311
  + color: @colorText;
302
312
  + background: @colorTextSecondary;
303
313
  + background-color: @colorTextTertiary;
304
314
  + border: 1px solid @colorBorder;
315
+ + font-size: @fontSizeSM;
305
316
  }
306
317
  }
307
318
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oceanbase/codemod",
3
- "version": "0.4.16",
3
+ "version": "1.0.0-alpha.0",
4
4
  "description": "Codemod for OceanBase Design upgrade",
5
5
  "keywords": [
6
6
  "oceanbase",
@@ -23,7 +23,7 @@
23
23
  "build": "father build"
24
24
  },
25
25
  "dependencies": {
26
- "@oceanbase/design": "^0.4.16",
26
+ "@oceanbase/design": "^1.0.0-alpha.0",
27
27
  "chalk": "^3.0.0",
28
28
  "command-exists": "^1.2.9",
29
29
  "execa": "^5.1.1",
@@ -47,5 +47,5 @@
47
47
  "enzyme": "^3.11.0",
48
48
  "enzyme-to-json": "^3.6.2"
49
49
  },
50
- "gitHead": "42879f277f4c72e7254f121861f9e8b8a8e024ce"
50
+ "gitHead": "1aff1c2acc2b9494ff83a86ed597b9f46a08f59c"
51
51
  }
@@ -4,10 +4,12 @@
4
4
  background-color: #faad14;
5
5
  border-color: #ff4d4f;
6
6
  scrollbar-color: #ffffff;
7
+ font-size: 14px;
7
8
  .content {
8
9
  color: rgba(0, 0, 0, 0.85);
9
10
  background: rgba(0, 0, 0,0.65);
10
11
  background-color: rgba(0,0,0,0.45);
11
12
  border: 1px solid #d9d9d9;
13
+ font-size: 12px;
12
14
  }
13
15
  }
@@ -5,10 +5,12 @@
5
5
  background-color: @colorWarning;
6
6
  border-color: @colorError;
7
7
  scrollbar-color: @colorBgContainer;
8
+ font-size: @fontSize;
8
9
  .content {
9
10
  color: @colorText;
10
11
  background: @colorTextSecondary;
11
12
  background-color: @colorTextTertiary;
12
13
  border: 1px solid @colorBorder;
14
+ font-size: @fontSizeSM;
13
15
  }
14
16
  }
@@ -4,10 +4,12 @@
4
4
  background-color: #FAAD14;
5
5
  border-color: #FF4D4F;
6
6
  scrollbar-color: #FFFFFF;
7
+ font-size: 14px;
7
8
  .content {
8
9
  color: rgba(0, 0, 0, 0.85);
9
10
  background: rgba(0, 0, 0,0.65);
10
11
  background-color: rgba(0,0,0,0.45);
11
12
  border: 1px solid #D9D9D9;
13
+ font-size: 12px;
12
14
  }
13
15
  }
@@ -5,10 +5,12 @@
5
5
  background-color: @colorWarning;
6
6
  border-color: @colorError;
7
7
  scrollbar-color: @colorBgContainer;
8
+ font-size: @fontSize;
8
9
  .content {
9
10
  color: @colorText;
10
11
  background: @colorTextSecondary;
11
12
  background-color: @colorTextTertiary;
12
13
  border: 1px solid @colorBorder;
14
+ font-size: @fontSizeSM;
13
15
  }
14
16
  }
@@ -4,6 +4,7 @@
4
4
  background-color: #faad14;
5
5
  border-color: #ff4d4f;
6
6
  scrollbar-color: #ffffff;
7
+ font-size: 14px;
7
8
  }
8
9
 
9
10
  .mixin-2 {
@@ -12,6 +13,7 @@
12
13
  background-color: #faad14;
13
14
  border-color: #ff4d4f;
14
15
  scrollbar-color: #ffffff;
16
+ font-size: 14px;
15
17
  }
16
18
 
17
19
  .container {
@@ -22,5 +24,6 @@
22
24
  background: rgba(0, 0, 0,0.65);
23
25
  background-color: rgba(0,0,0,0.45);
24
26
  border: 1px solid #d9d9d9;
27
+ font-size: 12px;
25
28
  }
26
29
  }
@@ -6,6 +6,7 @@
6
6
  background-color: @colorWarning;
7
7
  border-color: @colorError;
8
8
  scrollbar-color: @colorBgContainer;
9
+ font-size: @fontSize;
9
10
  }
10
11
 
11
12
  .mixin-2 {
@@ -14,6 +15,7 @@
14
15
  background-color: @colorWarning;
15
16
  border-color: @colorError;
16
17
  scrollbar-color: @colorBgContainer;
18
+ font-size: @fontSize;
17
19
  }
18
20
 
19
21
  .container {
@@ -24,5 +26,6 @@
24
26
  background: @colorTextSecondary;
25
27
  background-color: @colorTextTertiary;
26
28
  border: 1px solid @colorBorder;
29
+ font-size: @fontSizeSM;
27
30
  }
28
31
  }
@@ -5,11 +5,13 @@
5
5
  background: @colorSuccess;
6
6
  background-color: @colorWarning;
7
7
  border-color: @colorError;
8
+ font-size: 14px;
8
9
  .content {
9
10
  color: rgba(0, 0, 0, 0.85);
10
11
  background: rgba(0, 0, 0,0.65);
11
12
  background-color: rgba(0,0,0,0.45);
12
13
  border-color: rgb(0 0 0 / 45%);
13
14
  border: 1px solid #d9d9d9;
15
+ font-size: 12px;
14
16
  }
15
17
  }
@@ -4,11 +4,13 @@
4
4
  background: @colorSuccess;
5
5
  background-color: @colorWarning;
6
6
  border-color: @colorError;
7
+ font-size: @fontSize;
7
8
  .content {
8
9
  color: @colorText;
9
10
  background: @colorTextSecondary;
10
11
  background-color: @colorTextTertiary;
11
12
  border-color: @colorTextTertiary;
12
13
  border: 1px solid @colorBorder;
14
+ font-size: @fontSizeSM;
13
15
  }
14
16
  }
@@ -5,4 +5,5 @@
5
5
  background: @colorSuccess;
6
6
  background-color: @colorWarning;
7
7
  border-color: @colorError;
8
+ font-size: 14px;
8
9
  }
@@ -4,4 +4,5 @@
4
4
  background: @colorSuccess;
5
5
  background-color: @colorWarning;
6
6
  border-color: @colorError;
7
+ font-size: @fontSize;
7
8
  }
@@ -4,6 +4,7 @@ const useStyle1 = createStyles(() => {
4
4
  return {
5
5
  main: {
6
6
  background: '#1890ff',
7
+ fontSize: 14,
7
8
  },
8
9
  };
9
10
  });
@@ -12,6 +13,7 @@ const useStyle2 = createStyles(({}) => {
12
13
  return {
13
14
  main: {
14
15
  background: '#1890ff',
16
+ fontSize: 14,
15
17
  },
16
18
  };
17
19
  });
@@ -20,6 +22,7 @@ const useStyle3 = createStyles(({ token }) => {
20
22
  return {
21
23
  main: {
22
24
  background: '#1890ff',
25
+ fontSize: 14,
23
26
  },
24
27
  };
25
28
  });
@@ -8,6 +8,7 @@ const useStyle1 = createStyles((
8
8
  return {
9
9
  main: {
10
10
  background: token.colorInfo,
11
+ fontSize: token.fontSize,
11
12
  },
12
13
  };
13
14
  });
@@ -18,6 +19,7 @@ const useStyle2 = createStyles(({
18
19
  return {
19
20
  main: {
20
21
  background: token.colorInfo,
22
+ fontSize: token.fontSize,
21
23
  },
22
24
  };
23
25
  });
@@ -26,6 +28,7 @@ const useStyle3 = createStyles(({ token }) => {
26
28
  return {
27
29
  main: {
28
30
  background: token.colorInfo,
31
+ fontSize: token.fontSize,
29
32
  },
30
33
  };
31
34
  });
@@ -20,5 +20,9 @@ function getColorList() {
20
20
  type: 'border',
21
21
  color: '1px solid #d9d9d9',
22
22
  },
23
+ {
24
+ type: 'fontSize',
25
+ fontSize: 14,
26
+ },
23
27
  ];
24
28
  }
@@ -21,5 +21,9 @@ function getColorList() {
21
21
  type: 'border',
22
22
  color: `1px solid ${token.colorBorder}`,
23
23
  },
24
+ {
25
+ type: 'fontSize',
26
+ fontSize: token.fontSize,
27
+ },
24
28
  ];
25
29
  }
@@ -10,8 +10,8 @@ class Demo extends React.PureComponent {
10
10
  render() {
11
11
  return (
12
12
  <div>
13
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
14
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
13
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
14
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
15
15
  </div>
16
16
  );
17
17
  }
@@ -10,8 +10,8 @@ class Demo extends React.PureComponent {
10
10
  render() {
11
11
  return (
12
12
  <div>
13
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
14
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
13
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
14
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
15
15
  </div>
16
16
  );
17
17
  }
@@ -5,8 +5,8 @@ const Demo = () => {
5
5
  const { token } = theme.useToken();
6
6
  return (
7
7
  <div>
8
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
9
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
8
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
9
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
10
10
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
11
11
  </div>
12
12
  );
@@ -5,8 +5,8 @@ const Demo = () => {
5
5
  const { token } = theme.useToken();
6
6
  return (
7
7
  <div>
8
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
9
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
8
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
9
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
10
10
  <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
11
11
  </div>
12
12
  );
@@ -5,8 +5,8 @@ function Demo1() {
5
5
  const tokenList = ['rgb(0 0 0 / 45%)', '#006AFF', '#f3f6fc'];
6
6
  return (
7
7
  <div>
8
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
9
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
8
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
9
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
10
10
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
11
11
  </div>
12
12
  );
@@ -16,8 +16,8 @@ const Demo2 = () => {
16
16
  const tokenList = ['rgb(0 0 0 / 45%)', '#006AFF', '#f3f6fc'];
17
17
  return (
18
18
  <div>
19
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
20
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
19
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
20
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
21
21
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
22
22
  </div>
23
23
  );
@@ -6,8 +6,8 @@ function Demo1() {
6
6
  const tokenList = [token.colorTextTertiary, token.colorInfo, token.colorBgLayout];
7
7
  return (
8
8
  <div>
9
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
10
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
9
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
10
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
11
11
  <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
12
12
  </div>
13
13
  );
@@ -18,8 +18,8 @@ const Demo2 = () => {
18
18
  const tokenList = [token.colorTextTertiary, token.colorInfo, token.colorBgLayout];
19
19
  return (
20
20
  <div>
21
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
22
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
21
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
22
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
23
23
  <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
24
24
  </div>
25
25
  );
@@ -5,8 +5,8 @@ function getComponent1() {
5
5
  const tokenList = ['rgb(0 0 0 / 45%)', '#006AFF', '#f3f6fc'];
6
6
  return (
7
7
  <div>
8
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
9
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
8
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
9
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
10
10
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
11
11
  </div>
12
12
  );
@@ -16,8 +16,8 @@ const getComponent2 = () => {
16
16
  const tokenList = ['rgb(0 0 0 / 45%)', '#006AFF', '#f3f6fc'];
17
17
  return (
18
18
  <div>
19
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
20
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
19
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
20
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
21
21
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
22
22
  </div>
23
23
  );
@@ -27,8 +27,8 @@ export default () => {
27
27
  const tokenList = ['rgb(0 0 0 / 45%)', '#006AFF', '#f3f6fc'];
28
28
  return (
29
29
  <div>
30
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
31
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
30
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
31
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
32
32
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
33
33
  </div>
34
34
  );
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
- import { Alert, Button, token, Tooltip } from '@oceanbase/design';
2
+ import { Alert, Button, Tooltip, token } from '@oceanbase/design';
3
3
 
4
4
  function getComponent1() {
5
5
  const tokenList = [token.colorTextTertiary, token.colorInfo, token.colorBgLayout];
6
6
  return (
7
7
  <div>
8
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
9
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
8
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
9
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
10
10
  <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
11
11
  </div>
12
12
  );
@@ -16,8 +16,8 @@ const getComponent2 = () => {
16
16
  const tokenList = [token.colorTextTertiary, token.colorInfo, token.colorBgLayout];
17
17
  return (
18
18
  <div>
19
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
20
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
19
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
20
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
21
21
  <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
22
22
  </div>
23
23
  );
@@ -27,8 +27,8 @@ export default () => {
27
27
  const tokenList = [token.colorTextTertiary, token.colorInfo, token.colorBgLayout];
28
28
  return (
29
29
  <div>
30
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
31
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
30
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
31
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
32
32
  <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
33
33
  </div>
34
34
  );
@@ -5,8 +5,8 @@ function useComponent1 () {
5
5
  const tokenList = ['rgb(0 0 0 / 45%)', '#006AFF', '#f3f6fc'];
6
6
  return (
7
7
  <div>
8
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
9
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
8
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
9
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
10
10
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
11
11
  </div>
12
12
  );
@@ -16,8 +16,8 @@ const useComponent2 = () => {
16
16
  const tokenList = ['rgb(0 0 0 / 45%)', '#006AFF', '#f3f6fc'];
17
17
  return (
18
18
  <div>
19
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
20
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
19
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
20
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
21
21
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
22
22
  </div>
23
23
  );
@@ -6,8 +6,8 @@ function useComponent1 () {
6
6
  const tokenList = [token.colorTextTertiary, token.colorInfo, token.colorBgLayout];
7
7
  return (
8
8
  <div>
9
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
10
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
9
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
10
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
11
11
  <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
12
12
  </div>
13
13
  );
@@ -18,8 +18,8 @@ const useComponent2 = () => {
18
18
  const tokenList = [token.colorTextTertiary, token.colorInfo, token.colorBgLayout];
19
19
  return (
20
20
  <div>
21
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
22
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
21
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
22
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
23
23
  <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
24
24
  </div>
25
25
  );
@@ -4,13 +4,13 @@ import { Alert, Button, Tooltip } from '@oceanbase/design';
4
4
  const Demo = () => {
5
5
  const columns = [{
6
6
  render: () => {
7
- return <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />;
7
+ return <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" style={{ fontSize: 14 }} />;
8
8
  },
9
9
  }];
10
10
  return (
11
11
  <div>
12
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
13
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
12
+ <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9', fontSize: 14 }} />
13
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
14
14
  </div>
15
15
  );
16
16
  };
@@ -5,13 +5,13 @@ const Demo = () => {
5
5
  const { token } = theme.useToken();
6
6
  const columns = [{
7
7
  render: () => {
8
- return <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />;
8
+ return <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} style={{ fontSize: token.fontSize }} />;
9
9
  },
10
10
  }];
11
11
  return (
12
12
  <div>
13
- <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
14
- <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
13
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}`, fontSize: token.fontSize }} />
14
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError, fontSize: token.fontSizeSM }}></Button>
15
15
  </div>
16
16
  );
17
17
  };
@@ -7,4 +7,5 @@ const colorMap = {
7
7
  warning: '#faad14',
8
8
  error: '#ff4d4f',
9
9
  border: '1px solid #d9d9d9',
10
+ fontSize: 14,
10
11
  };
@@ -8,4 +8,5 @@ const colorMap = {
8
8
  warning: token.colorWarning,
9
9
  error: token.colorError,
10
10
  border: `1px solid ${token.colorBorder}`,
11
+ fontSize: token.fontSize,
11
12
  };
@@ -3,7 +3,7 @@ const fs = require('fs');
3
3
  const postcss = require('postcss');
4
4
  const postcssLess = require('postcss-less');
5
5
  const isDirectory = require('is-directory');
6
- const { tokenParse } = require('./utils/token');
6
+ const { tokenParse, propertyTokenParse } = require('./utils/token');
7
7
 
8
8
  /**
9
9
  * 搜索目录下所有的less文件
@@ -42,12 +42,22 @@ async function transform(file) {
42
42
  // 遍历 AST
43
43
  ast.walk(node => {
44
44
  if (node.type === 'decl') {
45
- const { key, token, formattedValue } = tokenParse(node.value);
46
- if (token) {
47
- node.value = formattedValue.replace(key, `@${token}`);
48
- hasToken = true;
49
- } else if (node.value?.includes('@')) {
45
+ // 首先尝试基于属性的 token 转换
46
+ // CSS 属性名转换为小驼峰写法(如 font-size -> fontSize)
47
+ const camelCaseProp = node.prop.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
48
+ const propertyResult = propertyTokenParse(camelCaseProp, node.value);
49
+ if (propertyResult) {
50
+ node.value = `@${propertyResult.token}`;
50
51
  hasToken = true;
52
+ } else {
53
+ // 然后尝试基于值的 token 转换
54
+ const { key, token, formattedValue } = tokenParse(node.value);
55
+ if (token) {
56
+ node.value = formattedValue.replace(key, `@${token}`);
57
+ hasToken = true;
58
+ } else if (node.value?.includes('@')) {
59
+ hasToken = true;
60
+ }
51
61
  }
52
62
  } else if (node.type === 'atrule' && node.name === 'import') {
53
63
  if (node.params === "'~@oceanbase/design/es/theme/index.less'") {
@@ -1,28 +1,17 @@
1
1
  const { upperFirst } = require('lodash');
2
2
  const { addSubmoduleImport } = require('./utils');
3
- const { tokenParse } = require('./utils/token');
3
+ const { tokenParse, propertyTokenParse } = require('./utils/token');
4
4
  const { printOptions } = require('./utils/config');
5
5
 
6
+ // 判断当前 path 是否为顶层 BlockStatement
6
7
  function isTopBlockStatement(path) {
8
+ // 判断当前节点类型是否为 BlockStatement
7
9
  const isBlockStatement = path.value.type === 'BlockStatement';
8
10
  let isTop = isBlockStatement && true;
9
11
  path = path.parentPath;
12
+ // 向上遍历父节点,直到遇到 Program 节点
10
13
  while (isTop && path.value.type !== 'Program') {
11
- // isTopBlockStatement => not wrapped by BlockStatement
12
- if (path.value.type === 'BlockStatement') {
13
- isTop = false;
14
- break;
15
- }
16
- path = path.parentPath;
17
- }
18
- return isTop;
19
- }
20
-
21
- function isTopIdentifier(path) {
22
- let isTop = true;
23
- path = path.parentPath;
24
- while (isTop && path.value.type !== 'Program') {
25
- // isTopIdentifier => not wrapped by BlockStatement
14
+ // 如果父节点也是 BlockStatement,则当前不是顶层 BlockStatement
26
15
  if (path.value.type === 'BlockStatement') {
27
16
  isTop = false;
28
17
  break;
@@ -32,6 +21,7 @@ function isTopIdentifier(path) {
32
21
  return isTop;
33
22
  }
34
23
 
24
+ // 判断字符串首字母是否为大写
35
25
  function isFirstUpperCase(str) {
36
26
  return upperFirst(str) === str;
37
27
  }
@@ -42,7 +32,160 @@ function shorthandProperty(property) {
42
32
  return property;
43
33
  }
44
34
 
45
- function importComponent(j, root, options) {
35
+ // 包装 JSX 属性值
36
+ function wrapJSXValue(value, isJSXAttribute) {
37
+ return isJSXAttribute ? `{${value}}` : value;
38
+ }
39
+
40
+ // 检查是否为 React 组件或 Hook
41
+ function isReactComponentOrHook(functionName) {
42
+ return functionName && (isFirstUpperCase(functionName) || functionName.startsWith('use'));
43
+ }
44
+
45
+ // 检查 BlockStatement 中是否包含 token 使用
46
+ function hasTokenUsage(j, path) {
47
+ return (
48
+ j(path).find(j.Identifier, {
49
+ name: name => name?.includes('token.'),
50
+ }).length > 0
51
+ );
52
+ }
53
+
54
+ // 检查 BlockStatement 中是否包含 useToken 语句
55
+ function hasUseTokenStatement(j, path) {
56
+ return (
57
+ j(path).find(j.Identifier, {
58
+ name: name => name.includes('useToken'),
59
+ }).length > 0
60
+ );
61
+ }
62
+
63
+ // 获取函数名称
64
+ function getFunctionName(path) {
65
+ const parentType = path.parentPath.value?.type;
66
+ if (parentType === 'FunctionDeclaration') {
67
+ return path.parentPath.value?.id?.name;
68
+ }
69
+ if (parentType === 'ArrowFunctionExpression') {
70
+ return path.parentPath.parentPath?.value?.id?.name;
71
+ }
72
+ return undefined;
73
+ }
74
+
75
+ // 创建 token 对象模式
76
+ function createTokenObjectPattern(j) {
77
+ return j.objectPattern([
78
+ shorthandProperty(j.property('init', j.identifier('token'), j.identifier('token'))),
79
+ ]);
80
+ }
81
+
82
+ // 检查对象模式中是否包含 token 属性
83
+ function hasTokenInObjectPattern(param) {
84
+ return param.properties.some(p => p.type === 'ObjectProperty' && p.key && p.key.name === 'token');
85
+ }
86
+
87
+ function processCreateStylesParams(j, root) {
88
+ const processedCreateStyles = new Set();
89
+
90
+ root
91
+ .find(j.CallExpression, {
92
+ callee: { name: 'createStyles' },
93
+ })
94
+ .forEach(path => {
95
+ const arrowFunc = path.value.arguments[0];
96
+ if (arrowFunc && arrowFunc.type === 'ArrowFunctionExpression') {
97
+ processedCreateStyles.add(path);
98
+
99
+ if (arrowFunc.params.length > 0) {
100
+ const param = arrowFunc.params[0];
101
+ if (param.type === 'ObjectPattern' && !hasTokenInObjectPattern(param)) {
102
+ // 如果参数对象中没有 token 属性,则插入 token 属性
103
+ param.properties.push(
104
+ shorthandProperty(j.property('init', j.identifier('token'), j.identifier('token')))
105
+ );
106
+ } else if (param.type !== 'ObjectPattern') {
107
+ // 如果参数不是对象结构,则替换为 { token }
108
+ arrowFunc.params[0] = createTokenObjectPattern(j);
109
+ }
110
+ } else {
111
+ // 如果没有参数,则插入 { token }
112
+ arrowFunc.params = [createTokenObjectPattern(j)];
113
+ }
114
+ }
115
+ });
116
+
117
+ return processedCreateStyles;
118
+ }
119
+
120
+ // 添加 token 导入到 BlockStatement
121
+ function addTokenImportToBlockStatement(j, root, path) {
122
+ const includeJSXElement = j(path).find(j.JSXElement).length > 0;
123
+ const functionName = getFunctionName(path);
124
+
125
+ if (includeJSXElement && isReactComponentOrHook(functionName)) {
126
+ const insertString = 'const { token } = theme.useToken()';
127
+ path.get('body').value.unshift(j.expressionStatement(j.identifier(insertString)));
128
+ addSubmoduleImport(j, root, {
129
+ moduleName: '@oceanbase/design',
130
+ importedName: 'theme',
131
+ importKind: 'value',
132
+ });
133
+ }
134
+ }
135
+
136
+ // 为函数组件和类组件添加 token 到现有导入
137
+ function addTokenToExistingImport(j, root) {
138
+ // 检查是否已经导入了 useToken 或 theme
139
+ const hasUseTokenImport =
140
+ root
141
+ .find(j.ImportDeclaration, {
142
+ source: { value: '@oceanbase/design' },
143
+ })
144
+ .find(j.ImportSpecifier, {
145
+ imported: { name: 'useToken' },
146
+ }).length > 0;
147
+
148
+ const hasThemeImport =
149
+ root
150
+ .find(j.ImportDeclaration, {
151
+ source: { value: '@oceanbase/design' },
152
+ })
153
+ .find(j.ImportSpecifier, {
154
+ imported: { name: 'theme' },
155
+ }).length > 0;
156
+
157
+ // 如果已经有 useToken 或 theme 导入,不需要添加 token 导入
158
+ if (hasUseTokenImport || hasThemeImport) {
159
+ return;
160
+ }
161
+
162
+ // 查找所有从 @oceanbase/design 的导入
163
+ const importDeclarations = root.find(j.ImportDeclaration, {
164
+ source: { value: '@oceanbase/design' },
165
+ });
166
+
167
+ if (importDeclarations.length === 0) {
168
+ return;
169
+ }
170
+
171
+ importDeclarations.forEach(importPath => {
172
+ const specifiers = importPath.value.specifiers;
173
+
174
+ // 检查是否已经有 token 导入
175
+ const hasTokenImport = specifiers.some(
176
+ spec => spec.type === 'ImportSpecifier' && spec.imported.name === 'token'
177
+ );
178
+
179
+ if (!hasTokenImport) {
180
+ // 添加 token 导入
181
+ const tokenSpecifier = j.importSpecifier(j.identifier('token'));
182
+ specifiers.push(tokenSpecifier);
183
+ }
184
+ });
185
+ }
186
+
187
+ // 处理字符串字面量的 token 替换
188
+ function processStringLiterals(j, root) {
46
189
  let hasChanged = false;
47
190
 
48
191
  const stringList = root.find(j.StringLiteral, {
@@ -51,130 +194,185 @@ function importComponent(j, root, options) {
51
194
  return !!token;
52
195
  },
53
196
  });
197
+
54
198
  if (stringList.length > 0) {
55
- // replace fixed style to token
56
199
  stringList.replaceWith(path => {
57
200
  hasChanged = true;
58
201
  const { key, token, formattedValue } = tokenParse(path.value.value);
59
202
  const isJSXAttribute = path.parentPath.value.type === 'JSXAttribute';
60
- let stringValue = `token.${token}`;
61
- let templateStringValue = `\`${formattedValue.replace(key, `\${token.${token}}`)}\``;
62
- // add {} wrapper for JSXAttribute
63
- if (isJSXAttribute) {
64
- stringValue = `{${stringValue}}`;
65
- templateStringValue = `{${templateStringValue}}`;
203
+
204
+ console.log(
205
+ 'Processing string:',
206
+ path.value.value,
207
+ 'isJSXAttribute:',
208
+ isJSXAttribute,
209
+ 'formattedValue:',
210
+ formattedValue,
211
+ 'key:',
212
+ key
213
+ );
214
+
215
+ if (formattedValue === key) {
216
+ // 完全匹配的情况,直接返回 token.xxx
217
+ const memberExpression = j.memberExpression(j.identifier('token'), j.identifier(token));
218
+ return isJSXAttribute ? j.jsxExpressionContainer(memberExpression) : memberExpression;
219
+ } else {
220
+ // 部分匹配的情况,返回模板字符串
221
+ const beforeToken = formattedValue.replace(key, '');
222
+ const templateString = j.templateLiteral(
223
+ [
224
+ j.templateElement({ raw: beforeToken, cooked: beforeToken }, false),
225
+ j.templateElement({ raw: '', cooked: '' }, true),
226
+ ],
227
+ [j.memberExpression(j.identifier('token'), j.identifier(token))]
228
+ );
229
+ return isJSXAttribute ? j.jsxExpressionContainer(templateString) : templateString;
66
230
  }
67
- return formattedValue === key ? j.identifier(stringValue) : j.identifier(templateStringValue);
68
231
  });
69
232
 
233
+ // 为包含 token 使用的顶级 BlockStatement 添加导入
70
234
  root
71
235
  .find(j.BlockStatement)
72
- // avoid duplicate insert for nested block statement
73
236
  .filter(path => isTopBlockStatement(path))
74
237
  .forEach(path => {
75
- const includeToken =
76
- j(path).find(j.Identifier, {
77
- name: name => name?.includes('token.'),
78
- }).length > 0;
79
- if (includeToken) {
80
- const includeJSXElement = j(path).find(j.JSXElement).length > 0;
81
- const includeUseTokenStatement =
82
- j(path).find(j.Identifier, {
83
- name: name => name.includes('useToken'),
84
- }).length > 0;
85
- const parentType = path.parentPath.value?.type;
86
- const functionName =
87
- parentType === 'FunctionDeclaration'
88
- ? path.parentPath.value?.id?.name
89
- : parentType === 'ArrowFunctionExpression'
90
- ? path.parentPath.parentPath?.value?.id?.name
91
- : undefined;
92
- const calleeName = path.parentPath.parentPath?.parentPath?.value?.callee?.name;
93
- if (
94
- includeJSXElement &&
95
- functionName &&
96
- // React function component or React hooks
97
- (isFirstUpperCase(functionName) || functionName.startsWith('use'))
98
- ) {
99
- // avoid duplicate insert when it's existed
100
- if (!includeUseTokenStatement) {
101
- const insertString = 'const { token } = theme.useToken()';
102
- // insert `const { token } = theme.useToken()`
103
- path.get('body').value.unshift(j.expressionStatement(j.identifier(insertString)));
104
- // import `theme` from @oceanbase/design
105
- addSubmoduleImport(j, root, {
106
- moduleName: '@oceanbase/design',
107
- importedName: 'theme',
108
- importKind: 'value',
109
- });
110
- }
111
- }
112
- // antd-style createStyles
113
- else if (parentType === 'ArrowFunctionExpression' && calleeName === 'createStyles') {
114
- const arrowFunc = path.parentPath?.parentPath?.value?.[0];
115
- if (arrowFunc && arrowFunc.type === 'ArrowFunctionExpression') {
116
- let hasToken = false;
117
- if (arrowFunc.params.length > 0) {
118
- const param = arrowFunc.params[0];
119
- if (param.type === 'ObjectPattern') {
120
- hasToken = param.properties.some(
121
- p => p.type === 'ObjectProperty' && p.key && p.key.name === 'token'
122
- );
123
- // 如果参数对象中没有 token 属性,则插入 token 属性
124
- if (!hasToken) {
125
- param.properties.push(
126
- shorthandProperty(
127
- j.property('init', j.identifier('token'), j.identifier('token'))
128
- )
129
- );
130
- }
131
- } else {
132
- // 如果参数不是对象结构,则替换为 { token }
133
- arrowFunc.params[0] = j.objectPattern([
134
- shorthandProperty(
135
- j.property('init', j.identifier('token'), j.identifier('token'))
136
- ),
137
- ]);
138
- }
139
- } else {
140
- // 如果没有参数,则插入 { token }
141
- arrowFunc.params = [
142
- j.objectPattern([
143
- shorthandProperty(
144
- j.property('init', j.identifier('token'), j.identifier('token'))
145
- ),
146
- ]),
147
- ];
148
- }
149
- }
150
- } else {
151
- // React class component and static file (not react component)
152
- // import `token` from @oceanbase/design
153
- addSubmoduleImport(j, root, {
154
- moduleName: '@oceanbase/design',
155
- importedName: 'token',
156
- importKind: 'value',
157
- });
158
- }
238
+ if (hasTokenUsage(j, path) && !hasUseTokenStatement(j, path)) {
239
+ addTokenImportToBlockStatement(j, root, path);
159
240
  }
160
241
  });
242
+ }
161
243
 
162
- root
163
- .find(j.Identifier)
164
- .filter(path => isTopIdentifier(path) && path.value.name?.includes('token.'))
165
- .forEach(() => {
166
- // import `token` from @oceanbase/design
167
- addSubmoduleImport(j, root, {
168
- moduleName: '@oceanbase/design',
169
- importedName: 'token',
170
- importKind: 'value',
171
- });
172
- });
244
+ return hasChanged;
245
+ }
246
+
247
+ function importComponent(j, root, options) {
248
+ let hasChanged = false;
249
+
250
+ // 处理字符串字面量
251
+ hasChanged = processStringLiterals(j, root) || hasChanged;
252
+
253
+ // 处理对象属性值(如 fontSize: 14)
254
+ const objectPropertyChanged = processObjectProperties(j, root);
255
+ hasChanged = objectPropertyChanged || hasChanged;
256
+
257
+ return hasChanged;
258
+ }
259
+
260
+ // 处理对象属性
261
+ function processObjectProperties(j, root) {
262
+ let hasChanged = false;
263
+
264
+ const objectPropertyList = root.find(j.ObjectProperty, {
265
+ key: { type: 'Identifier' },
266
+ value: { type: 'NumericLiteral' },
267
+ });
268
+
269
+ if (objectPropertyList.length > 0) {
270
+ objectPropertyList.replaceWith(path => {
271
+ const propertyName = path.value.key.name;
272
+ const propertyValue = path.value.value.value;
273
+
274
+ const tokenResult = propertyTokenParse(propertyName, propertyValue);
275
+ if (tokenResult) {
276
+ hasChanged = true;
277
+ const isJSXAttribute = path.parentPath.value.type === 'JSXAttribute';
278
+ const stringValue = wrapJSXValue(`token.${tokenResult.token}`, isJSXAttribute);
279
+ return j.objectProperty(j.identifier(propertyName), j.identifier(stringValue));
280
+ }
281
+ return path.value;
282
+ });
283
+
284
+ // 如果发生了替换,需要添加 token 导入
285
+ if (hasChanged) {
286
+ addTokenImportsForObjectProperties(j, root);
287
+ }
173
288
  }
174
289
 
175
290
  return hasChanged;
176
291
  }
177
292
 
293
+ // 为对象属性添加 token 导入
294
+ function addTokenImportsForObjectProperties(j, root) {
295
+ root
296
+ .find(j.BlockStatement)
297
+ .filter(path => isTopBlockStatement(path))
298
+ .forEach(path => {
299
+ if (hasTokenUsage(j, path) && !hasUseTokenStatement(j, path)) {
300
+ const calleeName = path.parentPath.parentPath?.parentPath?.value?.callee?.name;
301
+ // 跳过 createStyles 的情况,因为已经在上面处理了
302
+ if (calleeName !== 'createStyles') {
303
+ addTokenImportToBlockStatement(j, root, path);
304
+ }
305
+ }
306
+ });
307
+ }
308
+
309
+ // 检查是否应该添加顶层 token 导入
310
+ function shouldAddTopLevelTokenImport(j, root) {
311
+ // 检查是否有 createStyles 调用
312
+ const hasCreateStyles =
313
+ root.find(j.CallExpression, {
314
+ callee: { name: 'createStyles' },
315
+ }).length > 0;
316
+
317
+ // 检查是否使用了 theme.useToken()
318
+ const hasThemeUseToken =
319
+ root.find(j.CallExpression, {
320
+ callee: {
321
+ type: 'MemberExpression',
322
+ object: { name: 'theme' },
323
+ property: { name: 'useToken' },
324
+ },
325
+ }).length > 0;
326
+
327
+ // 检查是否导入了 theme
328
+ const hasThemeImport =
329
+ root
330
+ .find(j.ImportDeclaration, {
331
+ source: { value: '@oceanbase/design' },
332
+ })
333
+ .find(j.ImportSpecifier, {
334
+ imported: { name: 'theme' },
335
+ }).length > 0;
336
+
337
+ // 检查是否已经导入了 token
338
+ const hasTokenImport =
339
+ root
340
+ .find(j.ImportDeclaration, {
341
+ source: { value: '@oceanbase/design' },
342
+ })
343
+ .find(j.ImportSpecifier, {
344
+ imported: { name: 'token' },
345
+ }).length > 0;
346
+
347
+ // 检查是否有 token.xxx 的使用
348
+ const hasTokenUsage =
349
+ root.find(j.MemberExpression, {
350
+ object: { name: 'token' },
351
+ }).length > 0;
352
+
353
+ // 如果已经有 token 导入,不需要添加
354
+ if (hasTokenImport) {
355
+ return false;
356
+ }
357
+
358
+ // 如果有 createStyles 或 theme.useToken() 或 theme 导入,不需要添加顶层 token 导入
359
+ if (hasCreateStyles || hasThemeUseToken || hasThemeImport) {
360
+ return false;
361
+ }
362
+
363
+ // 如果有 token.xxx 的使用,需要添加导入
364
+ return hasTokenUsage;
365
+ }
366
+
367
+ // 添加顶层 token 导入
368
+ function addTopLevelTokenImport(j, root) {
369
+ addSubmoduleImport(j, root, {
370
+ moduleName: '@oceanbase/design',
371
+ importedName: 'token',
372
+ importKind: 'value',
373
+ });
374
+ }
375
+
178
376
  module.exports = (file, api, options) => {
179
377
  const j = api.jscodeshift;
180
378
  const root = j(file.source);
@@ -182,5 +380,38 @@ module.exports = (file, api, options) => {
182
380
  let hasChanged = false;
183
381
  hasChanged = importComponent(j, root, options) || hasChanged;
184
382
 
383
+ // 处理 createStyles 函数的参数
384
+ if (hasChanged) {
385
+ processCreateStylesParams(j, root);
386
+ }
387
+
388
+ // 如果有变化,检查是否需要添加 token 导入
389
+ if (hasChanged) {
390
+ // 检查是否有 token 使用
391
+ const hasTokenUsage =
392
+ root.find(j.MemberExpression, {
393
+ object: { name: 'token' },
394
+ }).length > 0;
395
+
396
+ if (hasTokenUsage) {
397
+ // 使用 shouldAddTopLevelTokenImport 函数来判断是否需要添加 token 导入
398
+ if (shouldAddTopLevelTokenImport(j, root)) {
399
+ // 检查是否有 @oceanbase/design 的导入
400
+ const hasOceanbaseImport =
401
+ root.find(j.ImportDeclaration, {
402
+ source: { value: '@oceanbase/design' },
403
+ }).length > 0;
404
+
405
+ if (hasOceanbaseImport) {
406
+ // 如果有 @oceanbase/design 导入,添加到现有导入
407
+ addTokenToExistingImport(j, root);
408
+ } else {
409
+ // 如果没有 @oceanbase/design 导入,添加顶层 token 导入
410
+ addTopLevelTokenImport(j, root);
411
+ }
412
+ }
413
+ }
414
+ }
415
+
185
416
  return hasChanged ? root.toSource(options.printOptions || printOptions) : null;
186
417
  };
@@ -35,6 +35,7 @@ const TOKEN_MAP = {
35
35
  '#1677ff': 'colorInfo',
36
36
  '#1890ff': 'colorInfo',
37
37
  '#40a9ff': 'colorInfo',
38
+ '#006aff': 'colorInfo',
38
39
  '#f7f9fb': 'colorInfoBg',
39
40
  '#e6f7ff': 'colorInfoBgHover',
40
41
  '#f3f9ff': 'colorInfoBgHover',
@@ -57,6 +58,7 @@ const TOKEN_MAP = {
57
58
  '#f0f2f5': 'colorBgLayout',
58
59
  '#fafafa': 'colorBgLayout',
59
60
  '#f7f8fc': 'colorBgLayout',
61
+ '#f3f6fc': 'colorBgLayout',
60
62
  'rgb(250,250,250)': 'colorBgLayout',
61
63
  '#ffffff': 'colorBgContainer',
62
64
  '#fff': 'colorBgContainer',
@@ -158,9 +160,46 @@ function tokenParse(value) {
158
160
  };
159
161
  }
160
162
 
163
+ // 基于属性名和数值的 token 映射
164
+ const PROPERTY_TOKEN_MAP = {
165
+ fontSize: {
166
+ 11: 'fontSizeSM',
167
+ 12: 'fontSizeSM',
168
+ 13: 'fontSize',
169
+ 14: 'fontSize',
170
+ 15: 'fontSizeLG',
171
+ 16: 'fontSizeLG',
172
+ },
173
+ };
174
+
175
+ function propertyTokenParse(propertyName, value) {
176
+ // 基于属性名和数值的 token 解析
177
+ const propertyMap = PROPERTY_TOKEN_MAP[propertyName];
178
+ if (!propertyMap) {
179
+ return null;
180
+ }
181
+
182
+ const stringValue = String(value);
183
+ // 提取数值部分(去掉单位)
184
+ const numericValue = stringValue.replace(/[^\d.]/g, '');
185
+ const token = propertyMap[numericValue];
186
+ if (!token) {
187
+ return null;
188
+ }
189
+
190
+ return {
191
+ key: stringValue,
192
+ token,
193
+ formattedValue: stringValue,
194
+ propertyName,
195
+ };
196
+ }
197
+
161
198
  module.exports = {
162
199
  TOKEN_MAP,
163
200
  TOKEN_MAP_KEYS,
164
201
  tokenParse,
202
+ PROPERTY_TOKEN_MAP,
203
+ propertyTokenParse,
165
204
  isLower,
166
205
  };