UNPKG

@alilc/lowcode-renderer-core

Version:
378 lines (357 loc) 10.3 kB
/* eslint-disable no-console */ /* eslint-disable no-new-func */ import logger from './logger'; import { isI18nData, isJSExpression } from '@alilc/lowcode-utils'; import { isEmpty } from 'lodash'; import IntlMessageFormat from 'intl-messageformat'; import pkg from '../../package.json'; window.sdkVersion = pkg.version; export { pick, isEqualWith as deepEqual, cloneDeep as clone, isEmpty, throttle, debounce } from 'lodash'; var EXPRESSION_TYPE = { JSEXPRESSION: 'JSExpression', JSFUNCTION: 'JSFunction', JSSLOT: 'JSSlot', JSBLOCK: 'JSBlock', I18N: 'i18n' }; /** * check if schema passed in is a valid schema * @name isSchema * @returns boolean */ export function isSchema(schema) { if (isEmpty(schema)) { return false; } // Leaf and Slot should be valid if (schema.componentName === 'Leaf' || schema.componentName === 'Slot') { return true; } if (Array.isArray(schema)) { return schema.every(function (item) { return isSchema(item); }); } // check if props is valid var isValidProps = function isValidProps(props) { if (!props) { return false; } if (isJSExpression(props)) { return true; } return typeof schema.props === 'object' && !Array.isArray(props); }; return !!(schema.componentName && isValidProps(schema.props)); } /** * check if schema passed in is a container type, including : Component Block Page * @param schema * @returns boolean */ export function isFileSchema(schema) { if (!isSchema(schema)) { return false; } return ['Page', 'Block', 'Component'].includes(schema.componentName); } /** * check if current page is nested within another page with same host * @returns boolean */ export function inSameDomain() { try { return window.parent !== window && window.parent.location.host === window.location.host; } catch (e) { return false; } } /** * get css styled name from schema`s fileName * FileName -> lce-file-name * @returns string */ export function getFileCssName(fileName) { if (!fileName) { return; } var name = fileName.replace(/([A-Z])/g, '-$1').toLowerCase(); return ("lce-" + name).split('-').filter(function (p) { return !!p; }).join('-'); } /** * check if a object is type of JSSlot * @returns string */ export function isJSSlot(obj) { if (!obj) { return false; } if (typeof obj !== 'object' || Array.isArray(obj)) { return false; } // Compatible with the old protocol JSBlock return [EXPRESSION_TYPE.JSSLOT, EXPRESSION_TYPE.JSBLOCK].includes(obj.type); } /** * get value from an object * @returns string */ export function getValue(obj, path, defaultValue) { if (defaultValue === void 0) { defaultValue = {}; } // array is not valid type, return default value if (Array.isArray(obj)) { return defaultValue; } if (isEmpty(obj) || typeof obj !== 'object') { return defaultValue; } var res = path.split('.').reduce(function (pre, cur) { return pre && pre[cur]; }, obj); if (res === undefined) { return defaultValue; } return res; } /** * 用于处理国际化字符串 * @param {*} key 语料标识 * @param {*} values 字符串模版变量 * @param {*} locale 国际化标识,例如 zh-CN、en-US * @param {*} messages 国际化语言包 */ export function getI18n(key, values, locale, messages) { if (values === void 0) { values = {}; } if (locale === void 0) { locale = 'zh-CN'; } if (messages === void 0) { messages = {}; } if (!messages || !messages[locale] || !messages[locale][key]) { return ''; } var formater = new IntlMessageFormat(messages[locale][key], locale); return formater.format(values); } /** * 判断当前组件是否能够设置ref * @param {*} Comp 需要判断的组件 */ export function canAcceptsRef(Comp) { var _Comp$prototype, _Comp$prototype2; var hasSymbol = typeof Symbol === 'function' && Symbol["for"]; var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol["for"]('react.forward_ref') : 0xead0; // eslint-disable-next-line max-len return (Comp === null || Comp === void 0 ? void 0 : Comp.$$typeof) === REACT_FORWARD_REF_TYPE || (Comp === null || Comp === void 0 ? void 0 : (_Comp$prototype = Comp.prototype) === null || _Comp$prototype === void 0 ? void 0 : _Comp$prototype.isReactComponent) || (Comp === null || Comp === void 0 ? void 0 : (_Comp$prototype2 = Comp.prototype) === null || _Comp$prototype2 === void 0 ? void 0 : _Comp$prototype2.setState) || Comp._forwardRef; } /** * transform array to a object * @param arr array to be transformed * @param key key of array item, which`s value will be used as key in result map * @param overwrite overwrite existing item in result or not * @returns object result map */ export function transformArrayToMap(arr, key, overwrite) { if (overwrite === void 0) { overwrite = true; } if (isEmpty(arr) || !Array.isArray(arr)) { return {}; } var res = {}; arr.forEach(function (item) { var curKey = item[key]; if (item[key] === undefined) { return; } if (res[curKey] && !overwrite) { return; } res[curKey] = item; }); return res; } /** * transform string to a function * @param str function in string form * @returns funtion */ export function transformStringToFunction(str) { if (typeof str !== 'string') { return str; } if (inSameDomain() && window.parent.__newFunc) { return window.parent.__newFunc("\"use strict\"; return " + str)(); } else { return new Function("\"use strict\"; return " + str)(); } } /** * 对象类型JSExpression,支持省略this * @param str expression in string form * @param self scope object * @returns funtion */ function parseExpression(a, b, c) { if (c === void 0) { c = false; } var str; var self; var thisRequired; var logScope; if (typeof a === 'object' && b === undefined) { str = a.str; self = a.self; thisRequired = a.thisRequired; logScope = a.logScope; } else { str = a; self = b; thisRequired = c; } try { var contextArr = ['"use strict";', 'var __self = arguments[0];']; contextArr.push('return '); var tarStr; tarStr = (str.value || '').trim(); // NOTE: use __self replace 'this' in the original function str // may be wrong in extreme case which contains '__self' already tarStr = tarStr.replace(/this(\W|$)/g, function (_a, b) { return "__self" + b; }); tarStr = contextArr.join('\n') + tarStr; // 默认调用顶层窗口的parseObj, 保障new Function的window对象是顶层的window对象 if (inSameDomain() && window.parent.__newFunc) { return window.parent.__newFunc(tarStr)(self); } var code = "with(" + (thisRequired ? '{}' : '$scope || {}') + ") { " + tarStr + " }"; return new Function('$scope', code)(self); } catch (err) { var _self$__self, _self; logger.error((logScope || '') + " parseExpression.error", err, str, (_self$__self = (_self = self) === null || _self === void 0 ? void 0 : _self.__self) !== null && _self$__self !== void 0 ? _self$__self : self); return undefined; } } export { parseExpression }; export function parseThisRequiredExpression(str, self) { return parseExpression(str, self, true); } /** * capitalize first letter * @param word string to be proccessed * @returns string capitalized string */ export function capitalizeFirstLetter(word) { if (!word || !isString(word) || word.length === 0) { return word; } return word[0].toUpperCase() + word.slice(1); } /** * check str passed in is a string type of not * @param str obj to be checked * @returns boolean */ export function isString(str) { return {}.toString.call(str) === '[object String]'; } /** * check if obj is type of variable structure * @param obj object to be checked * @returns boolean */ export function isVariable(obj) { if (!obj || Array.isArray(obj)) { return false; } return typeof obj === 'object' && (obj === null || obj === void 0 ? void 0 : obj.type) === 'variable'; } /** * 将 i18n 结构,降级解释为对 i18n 接口的调用 * @param i18nInfo object * @param self context */ export function parseI18n(i18nInfo, self) { return parseExpression({ type: EXPRESSION_TYPE.JSEXPRESSION, value: "this.i18n('" + i18nInfo.key + "')" }, self); } /** * for each key in targetObj, run fn with the value of the value, and the context paased in. * @param targetObj object that keys will be for each * @param fn function that process each item * @param context */ export function forEach(targetObj, fn, context) { if (!targetObj || Array.isArray(targetObj) || isString(targetObj) || typeof targetObj !== 'object') { return; } Object.keys(targetObj).forEach(function (key) { return fn.call(context, targetObj[key], key); }); } export function parseData(schema, self, options) { if (options === void 0) { options = {}; } if (isJSExpression(schema)) { return parseExpression({ str: schema, self: self, thisRequired: options.thisRequiredInJSE, logScope: options.logScope }); } else if (isI18nData(schema)) { return parseI18n(schema, self); } else if (typeof schema === 'string') { return schema.trim(); } else if (Array.isArray(schema)) { return schema.map(function (item) { return parseData(item, self, options); }); } else if (typeof schema === 'function') { return schema.bind(self); } else if (typeof schema === 'object') { // 对于undefined及null直接返回 if (!schema) { return schema; } var res = {}; forEach(schema, function (val, key) { if (key.startsWith('__')) { return; } res[key] = parseData(val, self, options); }); return res; } return schema; } /** * process params for using in a url query * @param obj params to be processed * @returns string */ export function serializeParams(obj) { var result = []; forEach(obj, function (val, key) { if (val === null || val === undefined || val === '') { return; } if (typeof val === 'object') { result.push(key + "=" + encodeURIComponent(JSON.stringify(val))); } else { result.push(key + "=" + encodeURIComponent(val)); } }); return result.join('&'); }