@oceanbase/codemod 1.0.0-alpha.0 → 1.0.0-alpha.2

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 (23) hide show
  1. package/bin/upgrade-list.json +8 -5
  2. package/package.json +3 -3
  3. package/transforms/__testfixtures__/less-to-token/exist-import-url.input.less +10 -0
  4. package/transforms/__testfixtures__/less-to-token/exist-import-url.output.less +10 -0
  5. package/transforms/__testfixtures__/less-to-token/exist-import.input.less +10 -0
  6. package/transforms/__testfixtures__/less-to-token/exist-import.output.less +10 -0
  7. package/transforms/__testfixtures__/style-to-token/anonymous-function.input.js +13 -0
  8. package/transforms/__testfixtures__/style-to-token/anonymous-function.output.js +14 -0
  9. package/transforms/__testfixtures__/style-to-token/antd-style.input.js +2 -2
  10. package/transforms/__testfixtures__/style-to-token/antd-style.output.js +1 -1
  11. package/transforms/__testfixtures__/style-to-token/class-component.input.js +1 -1
  12. package/transforms/__testfixtures__/style-to-token/existed-useToken.input.js +1 -1
  13. package/transforms/__testfixtures__/style-to-token/function-component.input.js +2 -2
  14. package/transforms/__testfixtures__/style-to-token/function.input.js +2 -2
  15. package/transforms/__testfixtures__/style-to-token/hooks.input.js +1 -1
  16. package/transforms/__testfixtures__/style-to-token/single-function.input.js +5 -0
  17. package/transforms/__testfixtures__/style-to-token/single-function.output.js +7 -0
  18. package/transforms/__tests__/less-to-token.test.ts +2 -0
  19. package/transforms/__tests__/style-to-token.test.ts +2 -0
  20. package/transforms/less-to-token.js +8 -2
  21. package/transforms/style-to-token.js +61 -21
  22. package/transforms/utils/index.js +8 -0
  23. package/transforms/utils/token.js +2 -1
@@ -1,18 +1,21 @@
1
1
  {
2
2
  "@oceanbase/design": {
3
- "version": "^0.4.0"
3
+ "version": "^1.0.0-alpha.0"
4
4
  },
5
5
  "@oceanbase/icons": {
6
- "version": "^0.4.0"
6
+ "version": "^1.0.0-alpha.0"
7
7
  },
8
8
  "@oceanbase/ui": {
9
- "version": "^0.4.0"
9
+ "version": "^1.0.0-alpha.0"
10
10
  },
11
11
  "@oceanbase/charts": {
12
- "version": "^0.4.0"
12
+ "version": "^1.0.0-alpha.0"
13
13
  },
14
14
  "@oceanbase/util": {
15
- "version": "^0.4.0"
15
+ "version": "^1.0.0-alpha.0"
16
+ },
17
+ "@oceanbase/codemod": {
18
+ "version": "^1.0.0-alpha.0"
16
19
  },
17
20
  "react": {
18
21
  "version": "^16.9.0"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oceanbase/codemod",
3
- "version": "1.0.0-alpha.0",
3
+ "version": "1.0.0-alpha.2",
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": "^1.0.0-alpha.0",
26
+ "@oceanbase/design": "^1.0.0-alpha.2",
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": "1aff1c2acc2b9494ff83a86ed597b9f46a08f59c"
50
+ "gitHead": "72910b1a2b037811f3ed5561ee5e897d7b744135"
51
51
  }
@@ -0,0 +1,10 @@
1
+ @import url('~@oceanbase/design/es/theme/index.less');
2
+
3
+ .container {
4
+ color: rgba(0, 0, 0, 0.85);
5
+ background: rgba(0, 0, 0,0.65);
6
+ background-color: rgba(0,0,0,0.45);
7
+ border-color: rgb(0 0 0 / 45%);
8
+ border: 1px solid #d9d9d9;
9
+ font-size: 14px;
10
+ }
@@ -0,0 +1,10 @@
1
+ @import url('~@oceanbase/design/es/theme/index.less');
2
+
3
+ .container {
4
+ color: @colorText;
5
+ background: @colorTextSecondary;
6
+ background-color: @colorTextTertiary;
7
+ border-color: @colorTextTertiary;
8
+ border: 1px solid @colorBorder;
9
+ font-size: @fontSize;
10
+ }
@@ -0,0 +1,10 @@
1
+ @import '~@oceanbase/design/es/theme/index.less';
2
+
3
+ .container {
4
+ color: rgba(0, 0, 0, 0.85);
5
+ background: rgba(0, 0, 0,0.65);
6
+ background-color: rgba(0,0,0,0.45);
7
+ border-color: rgb(0 0 0 / 45%);
8
+ border: 1px solid #d9d9d9;
9
+ font-size: 14px;
10
+ }
@@ -0,0 +1,10 @@
1
+ @import '~@oceanbase/design/es/theme/index.less';
2
+
3
+ .container {
4
+ color: @colorText;
5
+ background: @colorTextSecondary;
6
+ background-color: @colorTextTertiary;
7
+ border-color: @colorTextTertiary;
8
+ border: 1px solid @colorBorder;
9
+ font-size: @fontSize;
10
+ }
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { Alert, Button, Tooltip } from '@oceanbase/design';
3
+
4
+ export default function () {
5
+ const tokenList = ['rgb(0 0 0 / 45%)', '#006AFF', '#f3f6fc'];
6
+ return (
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', fontSize: 14 }} />
9
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: 12 }}></Button>
10
+ <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
11
+ </div>
12
+ );
13
+ };
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { Alert, Button, theme, Tooltip } from '@oceanbase/design';
3
+
4
+ export default function () {
5
+ const { token } = theme.useToken();
6
+ const tokenList = [token.colorTextTertiary, token.colorInfo, token.colorBgLayout];
7
+ return (
8
+ <div>
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
+ <Tooltip color={token.colorBgContainer} backgroundColor={token.colorErrorBg} borderColor={token.colorBgLayout} border={`1px solid ${token.colorBgLayout}`} />
12
+ </div>
13
+ );
14
+ };
@@ -13,7 +13,7 @@ const useStyle2 = createStyles(({}) => {
13
13
  return {
14
14
  main: {
15
15
  background: '#1890ff',
16
- fontSize: 14,
16
+ fontSize: '14px',
17
17
  },
18
18
  };
19
19
  });
@@ -22,7 +22,7 @@ const useStyle3 = createStyles(({ token }) => {
22
22
  return {
23
23
  main: {
24
24
  background: '#1890ff',
25
- fontSize: 14,
25
+ fontSize: 12,
26
26
  },
27
27
  };
28
28
  });
@@ -28,7 +28,7 @@ const useStyle3 = createStyles(({ token }) => {
28
28
  return {
29
29
  main: {
30
30
  background: token.colorInfo,
31
- fontSize: token.fontSize,
31
+ fontSize: token.fontSizeSM,
32
32
  },
33
33
  };
34
34
  });
@@ -11,7 +11,7 @@ class Demo extends React.PureComponent {
11
11
  return (
12
12
  <div>
13
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>
14
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: '12px' }}></Button>
15
15
  </div>
16
16
  );
17
17
  }
@@ -6,7 +6,7 @@ const Demo = () => {
6
6
  return (
7
7
  <div>
8
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>
9
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: '12px' }}></Button>
10
10
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
11
11
  </div>
12
12
  );
@@ -6,7 +6,7 @@ function Demo1() {
6
6
  return (
7
7
  <div>
8
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>
9
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: '12px' }}></Button>
10
10
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
11
11
  </div>
12
12
  );
@@ -17,7 +17,7 @@ const Demo2 = () => {
17
17
  return (
18
18
  <div>
19
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>
20
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: '12px' }}></Button>
21
21
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
22
22
  </div>
23
23
  );
@@ -6,7 +6,7 @@ function getComponent1() {
6
6
  return (
7
7
  <div>
8
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>
9
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: '12px' }}></Button>
10
10
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
11
11
  </div>
12
12
  );
@@ -17,7 +17,7 @@ const getComponent2 = () => {
17
17
  return (
18
18
  <div>
19
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>
20
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: '12px' }}></Button>
21
21
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
22
22
  </div>
23
23
  );
@@ -17,7 +17,7 @@ const useComponent2 = () => {
17
17
  return (
18
18
  <div>
19
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>
20
+ <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F', fontSize: '12px' }}></Button>
21
21
  <Tooltip color="#ffffff" backgroundColor="#fff1f0" borderColor="#fafafa" border="1px solid #fafafa" />
22
22
  </div>
23
23
  );
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+
3
+ function getComponent() {
4
+ return <div style={{ fontSize: 16 }} />;
5
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+
3
+ import { token } from '@oceanbase/design';
4
+
5
+ function getComponent() {
6
+ return <div style={{ fontSize: token.fontSizeLG }} />;
7
+ }
@@ -9,6 +9,8 @@ const tests = [
9
9
  'case-insensitive',
10
10
  'mixin',
11
11
  'obui-less-token-to-token',
12
+ 'exist-import',
13
+ 'exist-import-url',
12
14
  ];
13
15
 
14
16
  describe(testUnit, () => {
@@ -3,7 +3,9 @@ import { defineTest } from 'jscodeshift/src/testUtils';
3
3
  const testUnit = 'style-to-token';
4
4
  const tests = [
5
5
  'function-component',
6
+ 'anonymous-function',
6
7
  'function',
8
+ 'single-function',
7
9
  'hooks',
8
10
  'class-component',
9
11
  'block-statement',
@@ -60,9 +60,15 @@ async function transform(file) {
60
60
  }
61
61
  }
62
62
  } else if (node.type === 'atrule' && node.name === 'import') {
63
- if (node.params === "'~@oceanbase/design/es/theme/index.less'") {
63
+ if (
64
+ node.params?.includes("'~@oceanbase/design/es/theme/index.less'") ||
65
+ node.params?.includes('"~@oceanbase/design/es/theme/index.less"')
66
+ ) {
64
67
  tokenLessImported = true;
65
- } else if (node.params === "'~@alipay/ob-ui/es/theme/index.less'") {
68
+ } else if (
69
+ node.params?.includes("'~@alipay/ob-ui/es/theme/index.less'") ||
70
+ node.params?.includes('"~@alipay/ob-ui/es/theme/index.less"')
71
+ ) {
66
72
  node.remove();
67
73
  }
68
74
  }
@@ -38,8 +38,28 @@ function wrapJSXValue(value, isJSXAttribute) {
38
38
  }
39
39
 
40
40
  // 检查是否为 React 组件或 Hook
41
- function isReactComponentOrHook(functionName) {
42
- return functionName && (isFirstUpperCase(functionName) || functionName.startsWith('use'));
41
+ function isReactComponentOrHook(functionName, path) {
42
+ // 如果有函数名,检查是否以大写字母开头或以 use 开头
43
+ if (functionName) {
44
+ return isFirstUpperCase(functionName) || functionName.startsWith('use');
45
+ }
46
+
47
+ // 对于匿名函数,检查是否是 export default function () {} 的形式
48
+ // 而不是 export default () => {} 的形式
49
+ if (path) {
50
+ const parentType = path.parentPath.value?.type;
51
+ if (parentType === 'FunctionDeclaration') {
52
+ // export default function () {} - 认为是 React 组件
53
+ return true;
54
+ }
55
+ if (parentType === 'ArrowFunctionExpression') {
56
+ // export default () => {} - 不认为是 React 组件
57
+ return false;
58
+ }
59
+ }
60
+
61
+ // 其他情况,默认不认为是 React 组件
62
+ return false;
43
63
  }
44
64
 
45
65
  // 检查 BlockStatement 中是否包含 token 使用
@@ -122,7 +142,7 @@ function addTokenImportToBlockStatement(j, root, path) {
122
142
  const includeJSXElement = j(path).find(j.JSXElement).length > 0;
123
143
  const functionName = getFunctionName(path);
124
144
 
125
- if (includeJSXElement && isReactComponentOrHook(functionName)) {
145
+ if (includeJSXElement && isReactComponentOrHook(functionName, path)) {
126
146
  const insertString = 'const { token } = theme.useToken()';
127
147
  path.get('body').value.unshift(j.expressionStatement(j.identifier(insertString)));
128
148
  addSubmoduleImport(j, root, {
@@ -130,6 +150,14 @@ function addTokenImportToBlockStatement(j, root, path) {
130
150
  importedName: 'theme',
131
151
  importKind: 'value',
132
152
  });
153
+ } else if (includeJSXElement) {
154
+ // 对于非 React 组件的函数,直接导入 token
155
+ addSubmoduleImport(j, root, {
156
+ moduleName: '@oceanbase/design',
157
+ importedName: 'token',
158
+ importKind: 'value',
159
+ after: 'react',
160
+ });
133
161
  }
134
162
  }
135
163
 
@@ -201,17 +229,6 @@ function processStringLiterals(j, root) {
201
229
  const { key, token, formattedValue } = tokenParse(path.value.value);
202
230
  const isJSXAttribute = path.parentPath.value.type === 'JSXAttribute';
203
231
 
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
232
  if (formattedValue === key) {
216
233
  // 完全匹配的情况,直接返回 token.xxx
217
234
  const memberExpression = j.memberExpression(j.identifier('token'), j.identifier(token));
@@ -261,13 +278,14 @@ function importComponent(j, root, options) {
261
278
  function processObjectProperties(j, root) {
262
279
  let hasChanged = false;
263
280
 
264
- const objectPropertyList = root.find(j.ObjectProperty, {
281
+ // 处理数字字面量
282
+ const numericPropertyList = root.find(j.ObjectProperty, {
265
283
  key: { type: 'Identifier' },
266
284
  value: { type: 'NumericLiteral' },
267
285
  });
268
286
 
269
- if (objectPropertyList.length > 0) {
270
- objectPropertyList.replaceWith(path => {
287
+ if (numericPropertyList.length > 0) {
288
+ numericPropertyList.replaceWith(path => {
271
289
  const propertyName = path.value.key.name;
272
290
  const propertyValue = path.value.value.value;
273
291
 
@@ -280,11 +298,33 @@ function processObjectProperties(j, root) {
280
298
  }
281
299
  return path.value;
282
300
  });
301
+ }
283
302
 
284
- // 如果发生了替换,需要添加 token 导入
285
- if (hasChanged) {
286
- addTokenImportsForObjectProperties(j, root);
287
- }
303
+ // 处理字符串字面量(如 fontSize: '14px')
304
+ const stringPropertyList = root.find(j.ObjectProperty, {
305
+ key: { type: 'Identifier' },
306
+ value: { type: 'StringLiteral' },
307
+ });
308
+
309
+ if (stringPropertyList.length > 0) {
310
+ stringPropertyList.replaceWith(path => {
311
+ const propertyName = path.value.key.name;
312
+ const propertyValue = path.value.value.value;
313
+
314
+ const tokenResult = propertyTokenParse(propertyName, propertyValue);
315
+ if (tokenResult) {
316
+ hasChanged = true;
317
+ const isJSXAttribute = path.parentPath.value.type === 'JSXAttribute';
318
+ const stringValue = wrapJSXValue(`token.${tokenResult.token}`, isJSXAttribute);
319
+ return j.objectProperty(j.identifier(propertyName), j.identifier(stringValue));
320
+ }
321
+ return path.value;
322
+ });
323
+ }
324
+
325
+ // 如果发生了替换,需要添加 token 导入
326
+ if (hasChanged) {
327
+ addTokenImportsForObjectProperties(j, root);
288
328
  }
289
329
 
290
330
  return hasChanged;
@@ -136,6 +136,14 @@ function addModuleImport(j, root, { pkgName, importSpecifier, importKind, before
136
136
  return 1;
137
137
  }
138
138
 
139
+ // 特殊处理:token 总是放在最后
140
+ if (a.imported && a.imported.name === 'token') {
141
+ return 1;
142
+ }
143
+ if (b.imported && b.imported.name === 'token') {
144
+ return -1;
145
+ }
146
+
139
147
  return a.imported.name.localeCompare(b.imported.name);
140
148
  });
141
149
  const importStatement = j.importDeclaration(mergedImportSpecifiers, j.literal(pkgName));
@@ -47,6 +47,7 @@ const TOKEN_MAP = {
47
47
  '#ff4d4f': 'colorError',
48
48
  '#f5222d': 'colorError',
49
49
  '#f8636b': 'colorError',
50
+ '#f93939': 'colorError',
50
51
  '#d9d9d9': 'colorBorder',
51
52
  '#bfbfbf': 'colorBorder',
52
53
  '#e8e8e8': 'colorBorder',
@@ -122,12 +123,12 @@ const TOKEN_MAP = {
122
123
  '#cdd5e4': 'colorBorder',
123
124
  '#f5f8fe': 'colorBgLayout',
124
125
  '#f5f7fa': 'colorBgLayout',
126
+ '#f8fafe': 'colorBgLayout',
125
127
  'rgba(140,140,140,0.1)': 'colorBgLayout',
126
128
  'rgb(240,242,245)': 'colorBgLayout',
127
129
  '#132039': 'colorText',
128
130
  '#364563': 'colorTextSecondary',
129
131
  '#8592ad': 'colorTextTertiary',
130
- '#f8fafe': 'colorFillQuaternary',
131
132
  };
132
133
 
133
134
  const TOKEN_MAP_KEYS = Object.keys(TOKEN_MAP).map(key => formatValue(key));