@schema-render/core-react
Version:
Through a set of simple JSON Schema, efficiently build a set of forms.
85 lines (84 loc) • 3.45 kB
JavaScript
import { cloneDeep, mapKeys, toLower } from "./tinyLodash";
export function isInvalidTraverseSchema({ properties }) {
return !properties || typeof properties !== 'object' || Array.isArray(properties);
}
export default function traverseSchema(schema, visitor, options) {
const opts = {
mapKey: 'renderType',
ignoreCase: true,
clone: true,
initialState: {},
initialStore: {},
...options
};
const finalSchema = opts.clone ? cloneDeep(schema) : schema;
// 将 visitor 转换成小写
visitor = mapKeys(visitor, (_, key)=>key.toLowerCase());
const traverse = ({ schema, path, state, store })=>{
if (isInvalidTraverseSchema(schema)) return;
Object.keys(schema.properties).forEach((field)=>{
var // 节点进入事件
_$$_enter, _special_enter, /**
* 节点退出事件
*/ _$$_exit, _$$Object_exit, _special_exit;
const subSchema = schema.properties[field];
const subPath = [
...path,
field
];
const currentState = cloneDeep(state);
const params = {
schema: subSchema,
parentSchema: schema,
path: subPath,
field,
state: currentState,
store
};
const innerTraverse = (innerParams)=>{
traverse({
schema: subSchema,
path: subPath,
state: currentState,
...innerParams,
store
});
};
// $$: 匹配所有的节点类型
const $$ = visitor.$$ ?? {};
const $$Object = visitor.$$object ?? {};
(_$$_enter = $$.enter) === null || _$$_enter === void 0 ? void 0 : _$$_enter.call($$, {
...params,
traverse: innerTraverse
});
// special: 匹配特定的节点类型
let nodeType = subSchema[opts.mapKey] ?? '';
nodeType = opts.ignoreCase ? toLower(nodeType) : nodeType;
const isObjectLike = toLower(nodeType).startsWith('object');
// 对象类型进入事件
if (isObjectLike) {
var _$$Object_enter;
(_$$Object_enter = $$Object.enter) === null || _$$Object_enter === void 0 ? void 0 : _$$Object_enter.call($$Object, {
...params,
traverse: innerTraverse
});
}
// 特定节点进入事件
const special = visitor[nodeType] ?? {};
(_special_enter = special.enter) === null || _special_enter === void 0 ? void 0 : _special_enter.call(special, {
...params,
traverse: innerTraverse
});
(_$$_exit = $$.exit) === null || _$$_exit === void 0 ? void 0 : _$$_exit.call($$, params);
isObjectLike && ((_$$Object_exit = $$Object.exit) === null || _$$Object_exit === void 0 ? void 0 : _$$Object_exit.call($$Object, params));
(_special_exit = special.exit) === null || _special_exit === void 0 ? void 0 : _special_exit.call(special, params);
});
};
traverse({
schema: finalSchema,
path: [],
state: opts.initialState,
store: opts.initialStore
});
return finalSchema;
}