Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support auto migrate your v3 form #73

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,51 @@ import { Modal } from 'antd';
});
```

### migrate your form v3 to v4

You can auto migrate your `v3 form` by `antd4-codemod src --migrateform`, when execute this command, you should insure your already upgrade `antd v4`, also recommend your already execute above command.This scripts can't migrate all incompatible `api`, so if your codes aren't standard code(like `Form Form.Item`).We recommend you execute the command migrate form file one by one.When a file migrate, you should check incompatible `api`
If `Form.Item` in your code is not a standard code, for example, alias `Form.Item` is `FormItem`, you can use `--formitem=FormItem` to rename `Form.Item`

```diff

- import { Form } from '@ant-design/compatible'; // remove compatible package
- import '@ant-design/compatible/assets/index.css'; // if not includes compatible package, remove css


-<Form className="login-form">
- <Form.Item>
- {getFieldDecorator('username', {
- rules: [{ required: true, message: 'Please input your username!' }],
- initialValue: 'antd',
- })(<Input />)}
+<Form
+ className="login-form"
+ initialValue={{
+ username: 'antd',
+ password: '123456'
+ }}>
+ <Form.Item
+ name='username'
+ rules={[{ required: true, message: 'Please input your username!' }]}>
+ <Input />
</Form.Item>
<div>
- {getFieldDecorator('password', {
- initialValue: '123456',
- rules: [{ required: true, message: 'Please input your Password!' }],
- })(<Input />)}
+ <Form.Item
+ noStyle
+ name='password'
+ rules={[{ required: true, message: 'Please input your Password!' }]}><Input /></Form.Item>
</div>
</Form>;

- export default Form.create({})(Input) // remove Form.create
+ export default Input;

```

## License

MIT
48 changes: 48 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,54 @@ import { Modal } from 'antd';
});
```

### migrate your form v3 to v4

使用 `antd4-codemod src --migrateform` 来自动迁移你的旧版 `Form`,使用此命令时确保你已经升级到 v4,并且推荐已经执行上述其他迁移脚本。此脚本并不会帮你迁移所有不兼容的 `api`,所以如果不是标准写法的话(`Form Form.Item`)推荐对用此命令对单个文件边迁移边及时修改不兼容 `api`。

如果 `Form.Item` 不是标准的写法,譬如可能自己封装过为 `FormItem`,使用 `--formitem=FormItem` 来指定新的 `Form.Item` 命名。

```diff

- import { Form } from '@ant-design/compatible'; // 去掉兼容包的导入
- import '@ant-design/compatible/assets/index.css'; // 如果不在有兼容包,去除兼容包css

+ import { Form } from 'antd';

-<Form className="login-form">
- <Form.Item>
- {getFieldDecorator('username', {
- rules: [{ required: true, message: 'Please input your username!' }],
- initialValue: 'antd',
- })(<Input />)}
+<Form
+ className="login-form"
+ initialValue={{
+ username: 'antd',
+ password: '123456'
+ }}>
+ <Form.Item
+ name='username'
+ rules={[{ required: true, message: 'Please input your username!' }]}>
+ <Input />
</Form.Item>
<div>
- {getFieldDecorator('password', {
- initialValue: '123456',
- rules: [{ required: true, message: 'Please input your Password!' }],
- })(<Input />)}
+ <Form.Item
+ noStyle
+ name='password'
+ rules={[{ required: true, message: 'Please input your Password!' }]}><Input /></Form.Item>
</div>
</Form>;


- export default Form.create({})(Input) // 去除掉Form.create
+ export default Input;

```

## License

MIT
6 changes: 4 additions & 2 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,11 @@ function getRunnerArgs(

async function run(filePath, args = {}) {
const extraScripts = args.extraScripts ? args.extraScripts.split(',') : [];

const usedTransformers = args.migrateform
? ['v3-Form-to-FieldForm']
: transformers.concat(extraScripts);
// eslint-disable-next-line no-restricted-syntax
for (const transformer of transformers.concat(extraScripts)) {
for (const transformer of usedTransformers) {
// eslint-disable-next-line no-await-in-loop
await transform(transformer, 'babylon', filePath, args);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Form } from 'antd';

const input = <input />;

ReactDOM.render(
<div>
<Form.Item>
{getFieldDecorator('field1', {
rules: [{ required: true }]
})(<input style={{ width: 100 }} />)}
</Form.Item>
<Form.Item>
{getFieldDecorator('field2', {
rules: [{ required: true }]
})(input)}
</Form.Item>
</div>,
mountNode
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Form } from 'antd';

const input = <input />;

ReactDOM.render(
<div>
<Form.Item name='field1' rules={[{ required: true }]}>
<input style={{ width: 100 }} />
</Form.Item>
<Form.Item name='field2' rules={[{ required: true }]}>
{input}
</Form.Item>
</div>,
mountNode
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Form } from 'antd';

const input = <input />;

ReactDOM.render(
<div>
<div>
{getFieldDecorator('field1', {
rules: [{ required: true }]
})(<input style={{ width: 100 }} />)}
</div>
<div>
{getFieldDecorator('field2', {
rules: [{ required: true }]
})(input)}
</div>
</div>,
mountNode
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Form } from 'antd';

const input = <input />;

ReactDOM.render(
<div>
<div>
<Form.Item noStyle name='field1' rules={[{ required: true }]}><input style={{ width: 100 }} /></Form.Item>
</div>
<div>
<Form.Item noStyle name='field2' rules={[{ required: true }]}>{input}</Form.Item>
</div>
</div>,
mountNode
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Form, Icon as LegacyIcon } from '@ant-design/compatible';

class AntForm extends React.Component {
render() {
return (
<Form>
<Form.Item>
{getFieldDecorator('field1', {
rules: [{ required: true }],
initialValue: 'antd'
})(<input style={{ width: 100 }} />)}
</Form.Item>
</Form>
);
}
}

export default Form.create({})(AntForm);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Form } from 'antd';
import { Icon as LegacyIcon } from '@ant-design/compatible';

class AntForm extends React.Component {
render() {
return (
<Form
initialValue={{
field1: 'antd'
}}>
<Form.Item name='field1' rules={[{ required: true }]}>
<input style={{ width: 100 }} />
</Form.Item>
</Form>
);
}
}

export default AntForm;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Form } from 'antd';
import { FormItem } from 'components';

const input = <input />;

ReactDOM.render(
<div>
<FormItem>
{getFieldDecorator('field1', {
rules: [{ required: true }]
})(<input style={{ width: 100 }} />)}
</FormItem>
<FormItem>
{getFieldDecorator('field2', {
rules: [{ required: true }]
})(input)}
</FormItem>
</div>,
mountNode
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Form } from 'antd';
import { FormItem } from 'components';

const input = <input />;

ReactDOM.render(
<div>
<FormItem name='field1' rules={[{ required: true }]}>
<input style={{ width: 100 }} />
</FormItem>
<FormItem name='field2' rules={[{ required: true }]}>
{input}
</FormItem>
</div>,
mountNode
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Form } from 'antd';

const input = <input />;

const outerForm = (
<Form.Item>
{getFieldDecorator('outerform', {
initialValue: 'outer'
})(<input />)}
</Form.Item>
);

ReactDOM.render(
<Form>
<Form.Item>
{getFieldDecorator('field1', {
rules: [{ required: true }],
initialValue: 'antd'
})(<input style={{ width: 100 }} />)}
</Form.Item>
<Form.Item>
{getFieldDecorator(field2, {
rules: [{ required: true }],
initialValue: 'antd-1'
})(input)}
</Form.Item>
{outerForm}
</Form>,
mountNode
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Form } from 'antd';

const input = <input />;

const outerForm = (
<Form.Item name='outerform'>
<input />
</Form.Item>
);

ReactDOM.render(
<Form
initialValue={{
outerform: 'outer',
field1: 'antd',
[field2]: 'antd-1'
}}>
<Form.Item name='field1' rules={[{ required: true }]}>
<input style={{ width: 100 }} />
</Form.Item>
<Form.Item name={field2} rules={[{ required: true }]}>
{input}
</Form.Item>
{outerForm}
</Form>,
mountNode
);
39 changes: 39 additions & 0 deletions transforms/__tests__/v3-Form-to-FieldForm.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
jest.mock('../v3-Form-to-FieldForm', () => {
return Object.assign(require.requireActual('../v3-Form-to-FieldForm'), {
parser: 'babylon',
});
});

const tests = [
'getFieldDecorator',
'form-item',
'remove-useless',
'wrapper-form',
{
cmd: 'rename-formitem',
options: {
formitem: 'FormItem',
},
},
];

const defineTest = require('jscodeshift/dist/testUtils').defineTest;

const testUnit = 'v3-Form-to-FieldForm';

describe(testUnit, () => {
tests.forEach(test => {
const cmd = typeof test === 'string' ? test : test.cmd;
return defineTest(
__dirname,
testUnit,
{
antdPkgNames: ['antd', '@forked/antd', '@alipay/bigfish/antd'].join(
',',
),
...test.options,
},
`${testUnit}/${cmd}`,
);
});
});
18 changes: 18 additions & 0 deletions transforms/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,29 @@ function parseStrToArray(antdPkgNames) {
.map(n => n.trim());
}

function removeUnusedCompatiblecss(j, root) {
const isCompatibleAllRemoved = !root.find(j.ImportDeclaration, {
source: {
value: '@ant-design/compatible',
},
}).length;
if (isCompatibleAllRemoved) {
root
.find(j.ImportDeclaration, {
source: {
value: '@ant-design/compatible/assets/index.css',
},
})
.replaceWith();
}
}

module.exports = {
parseStrToArray,
addModuleDefaultImport,
addStyleModuleImport,
addSubmoduleImport,
removeEmptyModuleImport,
useVar,
removeUnusedCompatiblecss,
};
Loading