@oceanbase/codemod 1.0.0-alpha.0 → 1.0.0-alpha.1
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/bin/upgrade-list.json +8 -5
- package/package.json +3 -3
- package/transforms/__testfixtures__/style-to-token/anonymous-function.input.js +13 -0
- package/transforms/__testfixtures__/style-to-token/anonymous-function.output.js +14 -0
- package/transforms/__testfixtures__/style-to-token/antd-style.input.js +2 -2
- package/transforms/__testfixtures__/style-to-token/antd-style.output.js +1 -1
- package/transforms/__testfixtures__/style-to-token/class-component.input.js +1 -1
- package/transforms/__testfixtures__/style-to-token/existed-useToken.input.js +1 -1
- package/transforms/__testfixtures__/style-to-token/function-component.input.js +2 -2
- package/transforms/__testfixtures__/style-to-token/function.input.js +2 -2
- package/transforms/__testfixtures__/style-to-token/hooks.input.js +1 -1
- package/transforms/__testfixtures__/style-to-token/single-function.input.js +5 -0
- package/transforms/__testfixtures__/style-to-token/single-function.output.js +7 -0
- package/transforms/__tests__/style-to-token.test.ts +2 -0
- package/transforms/style-to-token.js +61 -21
- package/transforms/utils/index.js +8 -0
package/bin/upgrade-list.json
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"@oceanbase/design": {
|
|
3
|
-
"version": "^0.
|
|
3
|
+
"version": "^1.0.0-alpha.0"
|
|
4
4
|
},
|
|
5
5
|
"@oceanbase/icons": {
|
|
6
|
-
"version": "^0.
|
|
6
|
+
"version": "^1.0.0-alpha.0"
|
|
7
7
|
},
|
|
8
8
|
"@oceanbase/ui": {
|
|
9
|
-
"version": "^0.
|
|
9
|
+
"version": "^1.0.0-alpha.0"
|
|
10
10
|
},
|
|
11
11
|
"@oceanbase/charts": {
|
|
12
|
-
"version": "^0.
|
|
12
|
+
"version": "^1.0.0-alpha.0"
|
|
13
13
|
},
|
|
14
14
|
"@oceanbase/util": {
|
|
15
|
-
"version": "^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.
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
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.
|
|
26
|
+
"@oceanbase/design": "^1.0.0-alpha.1",
|
|
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": "
|
|
50
|
+
"gitHead": "47b1ebfa75581585b83252085dddd33fc2c072a5"
|
|
51
51
|
}
|
|
@@ -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:
|
|
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:
|
|
25
|
+
fontSize: 12,
|
|
26
26
|
},
|
|
27
27
|
};
|
|
28
28
|
});
|
|
@@ -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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
);
|
|
@@ -38,8 +38,28 @@ function wrapJSXValue(value, isJSXAttribute) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
// 检查是否为 React 组件或 Hook
|
|
41
|
-
function isReactComponentOrHook(functionName) {
|
|
42
|
-
|
|
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
|
-
|
|
281
|
+
// 处理数字字面量
|
|
282
|
+
const numericPropertyList = root.find(j.ObjectProperty, {
|
|
265
283
|
key: { type: 'Identifier' },
|
|
266
284
|
value: { type: 'NumericLiteral' },
|
|
267
285
|
});
|
|
268
286
|
|
|
269
|
-
if (
|
|
270
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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));
|