Skip to content

Commit

Permalink
✨ feat: add c2d2c getDiffPropsWithSchema and getSymbolMasterNameFromP…
Browse files Browse the repository at this point in the history
…rops func (#52)
  • Loading branch information
rdmclin2 committed Aug 1, 2023
1 parent c0b1c5f commit ea4ad31
Show file tree
Hide file tree
Showing 4 changed files with 544 additions and 1 deletion.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,11 @@
"leva": "^0.9.35",
"lodash.flatten": "^4.4.0",
"lodash.get": "^4.4.2",
"lodash.isarray": "^4.0.0",
"lodash.isempty": "^4.4.0",
"lodash.isequal": "^4.5.0",
"lodash.isnil": "^4.0.0",
"lodash.isobject": "^3.0.2",
"lodash.merge": "^4.6.2",
"lodash.omitby": "^4.6.0",
"lodash.template": "^4.5.0",
Expand Down
76 changes: 76 additions & 0 deletions src/utils/c2d2c.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { JSONSchema } from '@/types/schema';
import isArray from 'lodash.isarray';
import isEmpty from 'lodash.isempty';
import isEqual from 'lodash.isequal';
import isNil from 'lodash.isnil';
import isObject from 'lodash.isobject';
import omitBy from 'lodash.omitby';
import uniq from 'lodash.uniq';
import { ReactNodeElement } from '../types';
Expand All @@ -20,6 +23,79 @@ export const getDefaultValueFromSchema = (schema: JSONSchema) => {
return schema.default;
};

/**
* 获取去重后的 props
* @param props
* @param schema
*/
export const getDiffPropsWithSchema = (props: any, schema?: JSONSchema) => {
// 如果没有 schema,则使用原来的 props
if (!schema) return props;

const defaultProps = getDefaultValueFromSchema(schema);

if (!defaultProps) return props;

const filtered = Object.entries(props)
// 过滤掉默认值
.filter((entry) => {
const [key, value] = entry;

const defaultPropsValue = defaultProps[key];

// 如果该属性在默认值中不存在
if (typeof defaultProps[key] === 'undefined') return true;

// 或者与默认值不相等
return !isEqual(defaultPropsValue, value);
});

return Object.fromEntries(filtered);
};

/**
* 根据组件名称、props 生成 props 和 schema生成symbolMaster名称
*/
export const getSymbolMasterNameFromProps = (
pkg: string,
component: string,
props: any,
schema?: JSONSchema,
) => {
const validProps = getDiffPropsWithSchema(props, schema);

// 用一个递归方法来层层结构生成对象名称
const genName = (propsObj: object, parentKey?: string): string => {
return Object.entries(propsObj)
.map((entry) => {
const [key, value] = entry;

// 针对数组,需要结构它的内部对象
if (isArray(value)) {
return `${key}=[${value.map((item) => `{${genName(item)}}`).join(',')}]`;
}

// 嵌套对象 递归解析
if (isObject(value)) {
return genName(value, key);
}

// undefined 和 null 直接过滤
if (isNil(value)) {
return '';
}
// 普通的其他值直接返回
return `${parentKey ? `${parentKey}.` : ''}${key}=${value}`;
})
.filter((i) => i)
.join(',');
};

const propsStr = genName(validProps);

return `${pkg.replace('/', '-')}/${component}/${propsStr}`;
};

/**
* 获取组件库导入代码
*/
Expand Down
103 changes: 102 additions & 1 deletion src/utils/tests/c2d2c.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import {
generateImportCode,
generateJSXCode,
getDefaultValueFromSchema,
getDiffPropsWithSchema,
getSymbolMasterNameFromProps,
} from '../c2d2c';
import { schema } from './schema';
import { buttonSchema, menuSchema, radioGroup, schema, tagSchema } from './schema';

describe('getDefaultValueFromSchema', () => {
it('获取默认值', () => {
Expand All @@ -25,6 +27,105 @@ describe('getDefaultValueFromSchema', () => {
});
});

describe('getDiffPropsWithSchema', () => {
it('简单版本', () => {
const props = { checked: false, children: '未选中项', disabled: false };

expect(getDiffPropsWithSchema(props, radioGroup as any)).toEqual({
children: '未选中项',
});
});
it('没有 schema的情况', () => {
const props = { checked: false, children: '未选中项', disabled: false };

expect(getDiffPropsWithSchema(props)).toEqual(props);
});
it('schema 为空的情况', () => {
const props = { checked: false, children: '未选中项', disabled: false };

expect(getDiffPropsWithSchema(props, { type: 'object' })).toEqual(props);
});
});

describe('getSymbolMasterNameFromProps', () => {
it('正常生成', () => {
const name = getSymbolMasterNameFromProps(
'antd',
'Button',
{
danger: false,
isSubmit: false,
children: '主按钮',
ghost: false,
size: 'middle',
type: 'dashed',
shape: '',
disabled: false,
alignment: { vertical: 'top', horizontal: 'left' },
resize: { widthFollow: 'self', heightFollow: 'self' },
},
buttonSchema,
);

expect(name).toEqual(
'antd/Button/children=主按钮,type=dashed,alignment.vertical=top,alignment.horizontal=left,resize.widthFollow=self,resize.heightFollow=self',
);
});
it('包含 null 或者 undefined 的 props 需要被过滤', () => {
const name = getSymbolMasterNameFromProps(
'antd',
'Tag',
{
color: null,
closable: true,
a: undefined,
children: '标签123',
alignment: { vertical: 'top', horizontal: 'left' },
resize: { widthFollow: 'self', heightFollow: 'self' },
},
tagSchema,
);

expect(name).toEqual(
'antd/Tag/closable=true,children=标签123,alignment.vertical=top,alignment.horizontal=left,resize.widthFollow=self,resize.heightFollow=self',
);
});

it('包含数组、嵌套对象的处理方法', () => {
const props = {
size: 'large',
mode: 'vertical',
theme: 'dark',
items: [
{ label: '菜单项1', key: '2', disabled: false },
{ label: '菜单项2', key: '1', disabled: false },
{ label: '菜单项3', key: '3' },
{ label: '菜单项4' },
{ label: '' },
],
};
const name = getSymbolMasterNameFromProps('antd', 'Menu', props, menuSchema);
expect(name).toEqual(
'antd/Menu/size=large,theme=dark,items=[{label=菜单项1,key=2,disabled=false},{label=菜单项2,key=1,disabled=false},{label=菜单项3,key=3},{label=菜单项4},{label=}]',
);
});

it('没有schema时,也可以正常生成', () => {
const name = getSymbolMasterNameFromProps('antd', 'Button', {
danger: false,
children: '主按钮',
size: 'middle',
shape: null,
a: undefined,
alignment: { vertical: 'top', horizontal: 'left' },
});

expect(name).toEqual(
'antd/Button/danger=false,children=主按钮,size=middle,alignment.vertical=top,alignment.horizontal=left',
);
});
});

describe('generateImportCode', () => {
it('合成代码', () => {
const code = generateImportCode('antd', ['Button', 'Button', 'Alert']);
Expand Down

0 comments on commit ea4ad31

Please sign in to comment.