diff --git a/packages/editor-skeleton/src/register-defaults.ts b/packages/editor-skeleton/src/register-defaults.ts index 50e73b508..0ec8e8a06 100644 --- a/packages/editor-skeleton/src/register-defaults.ts +++ b/packages/editor-skeleton/src/register-defaults.ts @@ -4,6 +4,7 @@ import ArraySetter from './components/array-setter'; import ObjectSetter from './components/object-setter'; import MixedSetter from './components/mixed-setter'; import { isPlainObject } from '@ali/lowcode-utils'; +import parseJSFunc from './transducers/parse-func'; import parseProps from './transducers/parse-props'; import addonCombine from './transducers/addon-combine'; import SlotSetter from './components/slot-setter'; @@ -56,6 +57,9 @@ export const registerDefaults = () => { }); registerSetter('MixedSetter', MixedSetter); + // parseFunc + registerMetadataTransducer(parseJSFunc, 9, 'parse-func'); + // parseProps registerMetadataTransducer(parseProps, 10, 'parse-props'); diff --git a/packages/editor-skeleton/src/transducers/parse-func.ts b/packages/editor-skeleton/src/transducers/parse-func.ts new file mode 100644 index 000000000..8c02349ce --- /dev/null +++ b/packages/editor-skeleton/src/transducers/parse-func.ts @@ -0,0 +1,64 @@ +import { + FieldConfig, + TransformedComponentMetadata, + isJSFunction, +} from '@ali/lowcode-types'; +import { isPlainObject } from '@ali/lowcode-utils'; + +const leadingFnRe = /^function/; +const leadingFnNameRe = /^\w+\s*\(/; +/** + * 将函数字符串转成函数,支持几种类型 + * 类型一:() => {} / val => {} + * 类型二:setValue() {} + * 类型三:function() {} / function setValue() {} + * @param str + * @returns + */ +function transformStringToFunction(str: string) { + if (typeof str !== 'string') return str; + + let fn; + if (leadingFnNameRe.test(str) && !leadingFnRe.test(str)) { + str = `function ${str}`; + } + let fnBody = ` + return function() { + const self = this; + try { + return (${str}).apply(self, arguments); + } catch(e) { + console.log('call function which parsed by lowcode failed: ', e); + return e.message; + } + }; + `; + try { + // eslint-disable-next-line no-new-func + fn = new Function(fnBody)(); + } catch (e) { + console.error(str); + console.error(e.message); + } + return fn; +} + +function parseJSFunc(obj: any, enableAllowedKeys = true) { + if (!obj) return; + Object.keys(obj).forEach(key => { + const item = obj[key]; + if (isJSFunction(item)) { + obj[key] = transformStringToFunction(item.value); + } else if (Array.isArray(item)) { + item.forEach(o => parseJSFunc(o, enableAllowedKeys)); + } else if (isPlainObject(item)) { + parseJSFunc(item, enableAllowedKeys); + } + }); +} + +export default function (metadata: TransformedComponentMetadata): TransformedComponentMetadata { + parseJSFunc(metadata, false); + + return metadata; +} \ No newline at end of file