Skip to content

Commit

Permalink
feat: support auto migrate your v3 form
Browse files Browse the repository at this point in the history
  • Loading branch information
AshoneA committed Mar 2, 2020
1 parent 9f99946 commit 0676c4d
Show file tree
Hide file tree
Showing 16 changed files with 631 additions and 2 deletions.
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
47 changes: 47 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,53 @@ 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

0 comments on commit 0676c4d

Please sign in to comment.