Skip to content

Commit

Permalink
Merge pull request #215 from oceanbase/dengfuping-dev
Browse files Browse the repository at this point in the history
feat(codemod): Add style-to-token transform
  • Loading branch information
dengfuping committed Oct 24, 2023
2 parents 233181e + 166d41a commit b79a975
Show file tree
Hide file tree
Showing 11 changed files with 343 additions and 1 deletion.
99 changes: 99 additions & 0 deletions packages/codemod/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,102 @@ import utils and hooks from `@alipay/ob-util` to `@oceanbase/util`. Additionally

export default Demo;
```

### `style-to-token`

transform fixed css style to antd v5 design token.

- React function components:

```diff
import React from 'react';
- import { Alert, Button } from '@oceanbase/design';
+ import { Alert, Button, theme } from '@oceanbase/design';

const Demo = () => {
+ const { token } = theme.useToken();
return (
- <div>
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', borderColor: '#fafafa' }} />
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
- </div>
+ (<div>
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, borderColor: token.colorBgLayout }} />
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
+ </div>)
);
};

export default Demo;
```

- React class components:

```diff
import React from 'react';
- import { Alert, Button } from '@oceanbase/design';
+ import { Alert, Button, token } from '@oceanbase/design';

class Demo extends React.PureComponent {
constructor(props) {
super(props);
this.state = {};
}

render() {
return (
- <div>
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', borderColor: '#fafafa' }} />
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
- </div>
+ (<div>
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, borderColor: token.colorBgLayout }} />
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
+ </div>)
);
}
}

export default Demo;
```

- Static file (not react components):

```diff
+ import { token } from '@oceanbase/design';
const colorMap = {
- info: '#1890ff',
- success: '#52c41a',
- warning: '#faad14',
- error: '#ff4D4F',
+ info: token.colorInfo,
+ success: token.colorSuccess,
+ warning: token.colorWarning,
+ error: token.colorError,
};

function getColorList() {
return [
{
type: 'info',
- color: '#1890ff',
+ color: token.colorInfo,
},
{
type: 'success',
- color: '#52c41a',
+ color: token.colorSuccess,
},
{
type: 'warning',
- color: '#faad14',
+ color: token.colorWarning,
},
{
type: 'error',
- color: '#ff4D4F',
+ color: token.colorError,
}
];
}
```
1 change: 1 addition & 0 deletions packages/codemod/bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const transformers = [
'obui-to-oceanbase-design-and-ui',
'obutil-to-oceanbase-util',
'page-container-to-oceanbase-ui',
'style-to-token',
];

const dependencyProperties = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { Alert, Button } from '@oceanbase/design';

class Demo extends React.PureComponent {
constructor(props) {
super(props);
this.state = {};
}

render() {
return (
<div>
<Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', borderColor: '#fafafa' }} />
<Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
</div>
);
}
}

export default Demo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { Alert, Button, token } from '@oceanbase/design';

class Demo extends React.PureComponent {
constructor(props) {
super(props);
this.state = {};
}

render() {
return (
(<div>
<Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, borderColor: token.colorBgLayout }} />
<Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
</div>)
);
}
}

export default Demo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import { Alert, Button } from '@oceanbase/design';

const Demo = () => {
return (
<div>
<Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', borderColor: '#fafafa' }} />
<Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
</div>
);
};

export default Demo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import { Alert, Button, theme } from '@oceanbase/design';

const Demo = () => {
const { token } = theme.useToken();
return (
(<div>
<Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, borderColor: token.colorBgLayout }} />
<Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
</div>)
);
};

export default Demo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const colorMap = {
info: '#1890ff',
success: '#52c41a',
warning: '#faad14',
error: '#ff4D4F',
};

function getColorList() {
return [
{
type: 'info',
color: '#1890ff',
},
{
type: 'success',
color: '#52c41a',
},
{
type: 'warning',
color: '#faad14',
},
{
type: 'error',
color: '#ff4D4F',
}
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { token } from '@oceanbase/design';
const colorMap = {
info: token.colorInfo,
success: token.colorSuccess,
warning: token.colorWarning,
error: token.colorError,
};

function getColorList() {
return [
{
type: 'info',
color: token.colorInfo,
},
{
type: 'success',
color: token.colorSuccess,
},
{
type: 'warning',
color: token.colorWarning,
},
{
type: 'error',
color: token.colorError,
}
];
}
10 changes: 10 additions & 0 deletions packages/codemod/transforms/__tests__/style-to-token.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineTest } from 'jscodeshift/src/testUtils';

const testUnit = 'style-to-token';
const tests = ['function-component', 'class-component', 'static'];

describe(testUnit, () => {
tests.forEach(test =>
defineTest(__dirname, testUnit, {}, `${testUnit}/${test}`, { parser: 'babylon' })
);
});
110 changes: 110 additions & 0 deletions packages/codemod/transforms/style-to-token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
const { toLower } = require('lodash');
const { addSubmoduleImport } = require('./utils');
const { printOptions } = require('./utils/config');

const TOKEN_MAP = {
// antd fixed style => antd v5 token
'#f0f2f5': 'colorBgLayout',
'#fafafa': 'colorBgLayout',
'#fff': 'colorBgContainer',
'#ffffff': 'colorBgContainer',
'#1890ff': 'colorInfo',
'#52c41a': 'colorSuccess',
'#73d13d': 'colorSuccess',
'#faad14': 'colorWarning',
'#ff4d4f': 'colorError',
'#F5222D': 'colorError',
'#F8636B': 'colorError',
'#d9d9d9': 'colorBorder',
'#bfbfbf': 'colorBorder',
'rgba(0,0,0,0.85)': 'colorText',
'rgba(0,0,0,0.65)': 'colorTextSecondary',
'rgba(0,0,0,0.45)': 'colorTextTertiary',
'rgba(0,0,0,0.25)': 'colorTextQuaternary',
'rgba(0,0,0,0.2)': 'colorFillQuaternary',
'rgba(0,0,0,0.04)': 'colorBgLayout',
};

function trimAll(str) {
return str?.replace(/(\s)*/g, '');
}

function formatValue(value) {
return trimAll(toLower(value));
}

function importComponent(j, root, options) {
let hasChanged = false;

const stringList = root.find(j.StringLiteral, {
value: value => TOKEN_MAP[formatValue(value)],
});
if (stringList.length > 0) {
// replace inline style to token
stringList.replaceWith(path => {
hasChanged = true;
const stringValue = path.value.value;
const mapToken = TOKEN_MAP[formatValue(stringValue)];
return j.identifier(`token.${mapToken}`);
});

root.find(j.BlockStatement).forEach(path => {
const includeToken =
j(path).find(j.Identifier, {
name: name => name?.includes('token.'),
}).length > 0;
if (includeToken) {
const includeJsxElementList = j(path).find(j.JSXElement).length > 0;
const parentType = path.parentPath.value?.type;
// React function component
if (includeJsxElementList && parentType !== 'ClassMethod') {
const importString = `const { token } = theme.useToken()`;
path.get('body').value.unshift(j.expressionStatement(j.identifier(importString)));
// import theme from @oceanbase/design
addSubmoduleImport(j, root, {
moduleName: '@oceanbase/design',
importedName: 'theme',
importKind: 'value',
});
} else {
// React class component and static file (not react component)
// import token from @oceanbase/design
addSubmoduleImport(j, root, {
moduleName: '@oceanbase/design',
importedName: 'token',
importKind: 'value',
});
}
}

// const name = path.value.declarations[0].id.name;
// if (/^[A-Z]/.test(name)) {
// const init = path.value.declarations[0].init;
// const initCode = generate(path.value).code;
// if (
// init &&
// initCode.includes('token.') &&
// // avoid duplicate statement
// !initCode.includes('useToken()') &&
// init.type === 'ArrowFunctionExpression'
// ) {
// const codeBody = init.body;
// const importStyleString = `const { token } = theme.useToken();`;
// codeBody.body.unshift(j.blockStatement(importStyleString).program.body[0]);
// }
// }
});
}

return hasChanged;
}

module.exports = (file, api, options) => {
const j = api.jscodeshift;
const root = j(file.source);

let hasChanged = false;
hasChanged = importComponent(j, root, options) || hasChanged;

return hasChanged ? root.toSource(options.printOptions || printOptions) : null;
};
2 changes: 1 addition & 1 deletion packages/codemod/transforms/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ function addModuleImport(j, root, { pkgName, importSpecifier, importKind, before

if (before) {
insertImportBefore(j, root, { importStatement, importKind, beforeModule: before });
} else if (after) {
} else {
insertImportAfter(j, root, { importStatement, importKind, afterModule: after });
}

Expand Down

0 comments on commit b79a975

Please sign in to comment.