mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 19:52:51 +00:00
Merge branch 'release/1.0.6'
This commit is contained in:
commit
f0d8b852ef
@ -1,5 +1,9 @@
|
||||
module.exports = {
|
||||
extends: 'eslint-config-ali/typescript/react',
|
||||
parserOptions: {
|
||||
project: [], // for lint performance
|
||||
createDefaultProgram: false, // for lint performance
|
||||
},
|
||||
rules: {
|
||||
'react/no-multi-comp': 0,
|
||||
'no-unused-expressions': 0,
|
||||
@ -34,5 +38,7 @@ module.exports = {
|
||||
"@typescript-eslint/method-signature-style": 0,
|
||||
"@typescript-eslint/consistent-type-assertions": 0,
|
||||
"@typescript-eslint/no-useless-constructor": 0,
|
||||
'@typescript-eslint/dot-notation': 0, // for lint performance
|
||||
'@typescript-eslint/restrict-plus-operands': 0, // for lint performance
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"lerna": "4.0.0",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"packages": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-designer",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Designer for Ali LowCode Engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,10 +15,10 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-editor-core": "1.0.5",
|
||||
"@alilc/lowcode-shell": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-editor-core": "1.0.6",
|
||||
"@alilc/lowcode-shell": "1.0.6",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"classnames": "^2.2.6",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-react-16": "^1.15.5",
|
||||
|
||||
@ -52,7 +52,7 @@ export class Project {
|
||||
/**
|
||||
* 获取项目整体 schema
|
||||
*/
|
||||
getSchema(stage: TransformStage = TransformStage.Render): ProjectSchema {
|
||||
getSchema(stage: TransformStage = TransformStage.Save): ProjectSchema {
|
||||
return {
|
||||
...this.data,
|
||||
// TODO: future change this filter
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-editor-core",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Core Api for Ali lowCode engine",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
@ -14,8 +14,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^4.1.1",
|
||||
"intl-messageformat": "^9.3.1",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-editor-skeleton",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "alibaba lowcode editor skeleton",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -18,10 +18,10 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.20.12",
|
||||
"@alilc/lowcode-designer": "1.0.5",
|
||||
"@alilc/lowcode-editor-core": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-designer": "1.0.6",
|
||||
"@alilc/lowcode-editor-core": "1.0.6",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
|
||||
@ -314,6 +314,7 @@ body {
|
||||
display: none;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
z-index: 820;
|
||||
&.lc-area-visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
const { execSync } = require('child_process');
|
||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||
const fse = require('fs-extra');
|
||||
// read from lerna
|
||||
const lernaConfig = JSON.parse(fse.readFileSync('../../lerna.json', 'utf8'));
|
||||
const { version } = lernaConfig;
|
||||
|
||||
function getReleaseVersion() {
|
||||
const gitBranchName = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' });
|
||||
const reBranchVersion = /^(?:[\w-]+\/)(\d+\.\d+\.\d+)$/im;
|
||||
const match = reBranchVersion.exec(gitBranchName);
|
||||
if (!match) {
|
||||
throw new Error(`[engine] gitBranchName: ${gitBranchName} is not valid`);
|
||||
}
|
||||
|
||||
return match[1];
|
||||
}
|
||||
|
||||
const version = getReleaseVersion();
|
||||
|
||||
module.exports = ({ context, onGetWebpackConfig }) => {
|
||||
onGetWebpackConfig((config) => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-engine",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "An enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系",
|
||||
"main": "lib/engine-core.js",
|
||||
"module": "es/engine-core.js",
|
||||
@ -19,14 +19,14 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.12",
|
||||
"@alilc/lowcode-designer": "1.0.5",
|
||||
"@alilc/lowcode-editor-core": "1.0.5",
|
||||
"@alilc/lowcode-editor-skeleton": "1.0.5",
|
||||
"@alilc/lowcode-designer": "1.0.6",
|
||||
"@alilc/lowcode-editor-core": "1.0.6",
|
||||
"@alilc/lowcode-editor-skeleton": "1.0.6",
|
||||
"@alilc/lowcode-engine-ext": "^1.0.0",
|
||||
"@alilc/lowcode-plugin-designer": "1.0.5",
|
||||
"@alilc/lowcode-plugin-outline-pane": "1.0.5",
|
||||
"@alilc/lowcode-shell": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-plugin-designer": "1.0.6",
|
||||
"@alilc/lowcode-plugin-outline-pane": "1.0.6",
|
||||
"@alilc/lowcode-shell": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const { join } = require('path');
|
||||
const fse = require('fs-extra');
|
||||
// read from lerna
|
||||
const lernaConfig = JSON.parse(fse.readFileSync('../../lerna.json', 'utf8'));
|
||||
const { version } = lernaConfig;
|
||||
|
||||
let releaseVersion = version;
|
||||
|
||||
const distDir = join(__dirname, '../dist');
|
||||
|
||||
const distFileNames = ['engine-core.js'];
|
||||
|
||||
distFileNames.forEach(name => {
|
||||
const distFile = join(distDir, 'js', name);
|
||||
if (!fse.existsSync(distFile)) {
|
||||
console.warn(`[engine] distFile: ${distFile} doesn\'t exist`);
|
||||
return;
|
||||
}
|
||||
|
||||
const indexContent = fse.readFileSync(distFile, 'utf-8');
|
||||
|
||||
fse.writeFileSync(distFile, indexContent.replace('{{VERSION_PLACEHOLDER}}', releaseVersion));
|
||||
});
|
||||
|
||||
console.log('[engine] update engine version successfully!');
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-ignitor",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "点火器,bootstrap lce project",
|
||||
"main": "lib/index.js",
|
||||
"private": true,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-plugin-designer",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "alibaba lowcode editor designer plugin",
|
||||
"files": [
|
||||
"es",
|
||||
@ -18,9 +18,9 @@
|
||||
],
|
||||
"author": "xiayang.xy",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.0.5",
|
||||
"@alilc/lowcode-editor-core": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-designer": "1.0.6",
|
||||
"@alilc/lowcode-editor-core": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-plugin-outline-pane",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Outline pane for Ali lowCode engine",
|
||||
"files": [
|
||||
"es",
|
||||
@ -13,10 +13,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-designer": "1.0.5",
|
||||
"@alilc/lowcode-editor-core": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-designer": "1.0.6",
|
||||
"@alilc/lowcode-editor-core": "1.0.6",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16",
|
||||
"react-dom": "^16.7.0"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-rax-renderer",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Rax renderer for Ali lowCode engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -30,8 +30,8 @@
|
||||
"build": "build-scripts build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-renderer-core": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-renderer-core": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"rax-find-dom-node": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-rax-simulator-renderer",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "rax simulator renderer for alibaba lowcode designer",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -13,10 +13,10 @@
|
||||
"build:umd": "build-scripts build --config build.umd.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.0.5",
|
||||
"@alilc/lowcode-rax-renderer": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-designer": "1.0.6",
|
||||
"@alilc/lowcode-rax-renderer": "1.0.6",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"classnames": "^2.2.6",
|
||||
"driver-universal": "^3.1.3",
|
||||
"history": "^5.0.0",
|
||||
|
||||
@ -73,7 +73,10 @@ function cacheReactKey(el: Element): Element {
|
||||
if (REACT_KEY !== '') {
|
||||
return el;
|
||||
}
|
||||
REACT_KEY = Object.keys(el).find((key) => key.startsWith('__reactInternalInstance$')) || '';
|
||||
// react17 采用 __reactFiber 开头
|
||||
REACT_KEY = Object.keys(el).find(
|
||||
(key) => key.startsWith('__reactInternalInstance$') || key.startsWith('__reactFiber$'),
|
||||
) || '';
|
||||
if (!REACT_KEY && (el as HTMLElement).parentElement) {
|
||||
return cacheReactKey((el as HTMLElement).parentElement!);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-react-renderer",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "react renderer for ali lowcode engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -22,7 +22,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.21.16",
|
||||
"@alilc/lowcode-renderer-core": "1.0.5"
|
||||
"@alilc/lowcode-renderer-core": "1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
|
||||
6
packages/react-simulator-renderer/.babelrc
Normal file
6
packages/react-simulator-renderer/.babelrc
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"plugins": [
|
||||
["@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
["@babel/plugin-proposal-class-properties", { "loose": true }]
|
||||
]
|
||||
}
|
||||
6
packages/react-simulator-renderer/build.test.json
Normal file
6
packages/react-simulator-renderer/build.test.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"plugins": [
|
||||
"build-plugin-component",
|
||||
"@alilc/lowcode-test-mate/plugin/index.ts"
|
||||
]
|
||||
}
|
||||
33
packages/react-simulator-renderer/jest.config.js
Normal file
33
packages/react-simulator-renderer/jest.config.js
Normal file
@ -0,0 +1,33 @@
|
||||
const fs = require('fs');
|
||||
const { join } = require('path');
|
||||
const esModules = ['zen-logger'].join('|');
|
||||
const pkgNames = fs.readdirSync(join('..')).filter(pkgName => !pkgName.startsWith('.'));
|
||||
|
||||
const jestConfig = {
|
||||
// transform: {
|
||||
// '^.+\\.[jt]sx?$': 'babel-jest',
|
||||
// // '^.+\\.(ts|tsx)$': 'ts-jest',
|
||||
// // '^.+\\.(js|jsx)$': 'babel-jest',
|
||||
// },
|
||||
// testMatch: ['**/document/node/node.test.ts'],
|
||||
// testMatch: ['**/designer/builtin-hotkey.test.ts'],
|
||||
// testMatch: ['**/plugin/plugin-manager.test.ts'],
|
||||
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
|
||||
transformIgnorePatterns: [
|
||||
`/node_modules/(?!${esModules})/`,
|
||||
],
|
||||
setupFiles: ['./test/utils/host.ts'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||
collectCoverage: false,
|
||||
collectCoverageFrom: [
|
||||
'src/**/*.ts',
|
||||
'!src/**/*.d.ts',
|
||||
'!**/node_modules/**',
|
||||
],
|
||||
};
|
||||
|
||||
// 只对本仓库内的 pkg 做 mapping
|
||||
jestConfig.moduleNameMapper = {};
|
||||
jestConfig.moduleNameMapper[`^@alilc/lowcode\\-(${pkgNames.join('|')})$`] = '<rootDir>/../$1/src';
|
||||
|
||||
module.exports = jestConfig;
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-react-simulator-renderer",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "react simulator renderer for alibaba lowcode designer",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -11,14 +11,15 @@
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "build-scripts test --config build.test.json",
|
||||
"build": "NODE_OPTIONS=--max_old_space_size=8192 build-scripts build --skip-demo",
|
||||
"build:umd": "NODE_OPTIONS=--max_old_space_size=8192 build-scripts build --config build.umd.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.0.5",
|
||||
"@alilc/lowcode-react-renderer": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-designer": "1.0.6",
|
||||
"@alilc/lowcode-react-renderer": "1.0.6",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"classnames": "^2.2.6",
|
||||
"mobx": "^6.3.0",
|
||||
"mobx-react": "^7.2.0",
|
||||
|
||||
@ -530,7 +530,10 @@ function cacheReactKey(el: Element): Element {
|
||||
if (REACT_KEY !== '') {
|
||||
return el;
|
||||
}
|
||||
REACT_KEY = Object.keys(el).find((key) => key.startsWith('__reactInternalInstance$')) || '';
|
||||
// react17 采用 __reactFiber 开头
|
||||
REACT_KEY = Object.keys(el).find(
|
||||
(key) => key.startsWith('__reactInternalInstance$') || key.startsWith('__reactFiber$'),
|
||||
) || '';
|
||||
if (!REACT_KEY && (el as HTMLElement).parentElement) {
|
||||
return cacheReactKey((el as HTMLElement).parentElement!);
|
||||
}
|
||||
|
||||
81
packages/react-simulator-renderer/test/schema/basic.ts
Normal file
81
packages/react-simulator-renderer/test/schema/basic.ts
Normal file
@ -0,0 +1,81 @@
|
||||
export default {
|
||||
id: 'node_ockvuu8u911',
|
||||
css: 'body{background-color:#f2f3f5}',
|
||||
flows: [],
|
||||
props: {
|
||||
className: 'page_kvuu9hym',
|
||||
pageStyle: {
|
||||
backgroundColor: '#f2f3f5',
|
||||
},
|
||||
containerStyle: {},
|
||||
templateVersion: '1.0.0',
|
||||
},
|
||||
state: {},
|
||||
title: '',
|
||||
methods: {
|
||||
__initMethods__: {
|
||||
type: 'JSExpression',
|
||||
value: "function (exports, module) { \"use strict\";\n\nexports.__esModule = true;\nexports.func1 = func1;\nexports.helloPage = helloPage;\n\nfunction func1() {\n console.info('hello, this is a page function');\n}\n\nfunction helloPage() {\n // 你可以这么调用其他函数\n this.func1(); // 你可以这么调用组件的函数\n // this.$('textField_xxx').getValue();\n // 你可以这么使用「数据源面板」定义的「变量」\n // this.state.xxx\n // 你可以这么发送一个在「数据源面板」定义的「远程 API」\n // this.dataSourceMap['xxx'].load(data)\n // API 详见:https://go.alibaba-inc.com/help3/API\n} \n}",
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'node_ockvuu8u915',
|
||||
props: {
|
||||
fieldId: 'div_kvuu9gl1',
|
||||
behavior: 'NORMAL',
|
||||
__style__: {},
|
||||
customClassName: '',
|
||||
useFieldIdAsDomId: false,
|
||||
},
|
||||
title: '',
|
||||
children: [
|
||||
{
|
||||
id: 'node_ockvuu8u916',
|
||||
props: {
|
||||
content: {
|
||||
use: 'zh_CN',
|
||||
type: 'JSExpression',
|
||||
en_US: 'Tips content',
|
||||
value: '"我是一个简单的测试页面"',
|
||||
zh_CN: '我是一个简单的测试页面',
|
||||
extType: 'i18n',
|
||||
},
|
||||
fieldId: 'text_kvuu9gl2',
|
||||
maxLine: 0,
|
||||
behavior: 'NORMAL',
|
||||
__style__: {},
|
||||
showTitle: false,
|
||||
},
|
||||
title: '',
|
||||
condition: true,
|
||||
componentName: 'Text',
|
||||
},
|
||||
],
|
||||
condition: true,
|
||||
componentName: 'Div',
|
||||
},
|
||||
],
|
||||
condition: true,
|
||||
dataSource: {
|
||||
list: [],
|
||||
sync: true,
|
||||
online: [],
|
||||
offline: [],
|
||||
globalConfig: {
|
||||
fit: {
|
||||
type: 'JSExpression',
|
||||
value: "function main(){\n 'use strict';\n\nvar __compiledFunc__ = function fit(response) {\n var content = response.content !== undefined ? response.content : response;\n var error = {\n message: response.errorMsg || response.errors && response.errors[0] && response.errors[0].msg || response.content || '远程数据源请求出错,success is false'\n };\n var success = true;\n if (response.success !== undefined) {\n success = response.success;\n } else if (response.hasError !== undefined) {\n success = !response.hasError;\n }\n return {\n content: content,\n success: success,\n error: error\n };\n};\n return __compiledFunc__.apply(this, arguments);\n}",
|
||||
extType: 'function',
|
||||
},
|
||||
},
|
||||
},
|
||||
lifeCycles: {
|
||||
constructor: {
|
||||
type: 'JSExpression',
|
||||
value: "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
|
||||
extType: 'function',
|
||||
},
|
||||
},
|
||||
componentName: 'Page',
|
||||
};
|
||||
@ -0,0 +1,41 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Base should be render NotFoundComponent 1`] = `
|
||||
<div
|
||||
className="lce-page page_kvuu9hym"
|
||||
style={Object {}}
|
||||
>
|
||||
<div
|
||||
componentName="Div"
|
||||
>
|
||||
<div
|
||||
componentName="Text"
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Base should be render Text 1`] = `
|
||||
<div
|
||||
className="lce-page page_kvuu9hym"
|
||||
style={Object {}}
|
||||
>
|
||||
<div
|
||||
componentName="Div"
|
||||
>
|
||||
<div
|
||||
__designMode="design"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
componentId="node_ockvuu8u916"
|
||||
fieldId="text_kvuu9gl2"
|
||||
maxLine={0}
|
||||
showTitle={false}
|
||||
>
|
||||
我是一个简单的测试页面
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -0,0 +1,31 @@
|
||||
import renderer from 'react-test-renderer';
|
||||
import rendererContainer from '../../../src/renderer';
|
||||
import SimulatorRendererView from '../../../src/renderer-view';
|
||||
import { Text } from '../../utils/components';
|
||||
|
||||
describe('Base', () => {
|
||||
const component = renderer.create(
|
||||
<SimulatorRendererView
|
||||
rendererContainer={rendererContainer}
|
||||
/>
|
||||
);
|
||||
|
||||
it('should be render NotFoundComponent', () => {
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should be render Text', () => {
|
||||
// 更新 _componentsMap 值
|
||||
(rendererContainer as any)._componentsMap.Text = Text;// = host.designer.componentsMap;
|
||||
// 更新 components 列表
|
||||
(rendererContainer as any).buildComponents();
|
||||
|
||||
expect(!!(rendererContainer.components as any).Text).toBeTruthy();
|
||||
|
||||
rendererContainer.rerender();
|
||||
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
})
|
||||
@ -0,0 +1,7 @@
|
||||
export const Text = ({
|
||||
__tag,
|
||||
content,
|
||||
...props
|
||||
}: any) => (<div {...props}>{content}</div>);
|
||||
|
||||
export const Page = (props: any) => (<div>{props.children}</div>);
|
||||
75
packages/react-simulator-renderer/test/utils/host.ts
Normal file
75
packages/react-simulator-renderer/test/utils/host.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { Box, Breadcrumb, Form, Select, Input, Button, Table, Pagination, Dialog } from '@alifd/next';
|
||||
import defaultSchema from '../schema/basic';
|
||||
import { Page } from './components';
|
||||
|
||||
class Designer {
|
||||
componentsMap = {
|
||||
Box,
|
||||
Breadcrumb,
|
||||
'Breadcrumb.Item': Breadcrumb.Item,
|
||||
Form,
|
||||
'Form.Item': Form.Item,
|
||||
Select,
|
||||
Input,
|
||||
Button,
|
||||
'Button.Group': Button.Group,
|
||||
Table,
|
||||
Pagination,
|
||||
Dialog,
|
||||
Page,
|
||||
}
|
||||
}
|
||||
|
||||
class Host {
|
||||
designer = new Designer();
|
||||
|
||||
connect = () => {}
|
||||
|
||||
autorun = (fn: Function) => {
|
||||
fn();
|
||||
}
|
||||
|
||||
autoRender = true;
|
||||
|
||||
componentsConsumer = {
|
||||
consume() {}
|
||||
}
|
||||
|
||||
schema = defaultSchema;
|
||||
|
||||
project = {
|
||||
documents: [
|
||||
{
|
||||
id: '1',
|
||||
path: '/',
|
||||
fileName: '',
|
||||
export: () => {
|
||||
return this.schema;
|
||||
},
|
||||
getNode: () => {},
|
||||
}
|
||||
],
|
||||
get: () => ({}),
|
||||
}
|
||||
|
||||
setInstance() {}
|
||||
|
||||
designMode = 'design'
|
||||
|
||||
get() {}
|
||||
|
||||
injectionConsumer = {
|
||||
consume() {}
|
||||
}
|
||||
|
||||
/** 下列的函数或者方法是方便测试用 */
|
||||
mockSchema = (schema: any) => {
|
||||
this.schema = schema;
|
||||
};
|
||||
}
|
||||
|
||||
if (!(window as any).LCSimulatorHost) {
|
||||
(window as any).LCSimulatorHost = new Host();
|
||||
}
|
||||
|
||||
export default (window as any).LCSimulatorHost;
|
||||
@ -1,24 +1,41 @@
|
||||
module.exports = {
|
||||
transform: {
|
||||
'^.+\\.(ts|tsx)$': 'ts-jest',
|
||||
'^.+\\.(js|ts|tsx|jsx)$': 'babel-jest',
|
||||
'^.+\\.(css|less|scss)$': './test/mock/styleMock.js',
|
||||
},
|
||||
// testMatch: ['**/bugs/*.test.ts'],
|
||||
const fs = require('fs');
|
||||
const { join } = require('path');
|
||||
const esModules = ['zen-logger'].join('|');
|
||||
const pkgNames = fs.readdirSync(join('..')).filter(pkgName => !pkgName.startsWith('.'));
|
||||
|
||||
const jestConfig = {
|
||||
// transform: {
|
||||
// // '^.+\\.[jt]sx?$': 'babel-jest',
|
||||
// '^.+\\.(ts|tsx)$': 'ts-jest',
|
||||
// // '^.+\\.(js|jsx)$': 'babel-jest',
|
||||
// },
|
||||
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
|
||||
// transformIgnorePatterns: [
|
||||
// `/node_modules/(?!${esModules})/`,
|
||||
// ],
|
||||
testEnvironment: 'jsdom',
|
||||
// testMatch: ['**/*/common.test.ts'],
|
||||
transformIgnorePatterns: [
|
||||
`/node_modules/(?!${esModules})/`,
|
||||
],
|
||||
setupFiles: ['./tests/fixtures/unhandled-rejection.ts'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||
collectCoverage: false,
|
||||
collectCoverageFrom: [
|
||||
'src/**/*.{ts,tsx}',
|
||||
],
|
||||
moduleNameMapper: {
|
||||
'^.+.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
|
||||
},
|
||||
setupFilesAfterEnv: [
|
||||
'./test/setup.ts',
|
||||
'src/**/*.ts',
|
||||
'!src/**/*.d.ts',
|
||||
'!src/icons/**',
|
||||
'!src/locale/**',
|
||||
'!src/builtin-simulator/utils/**',
|
||||
'!src/plugin/sequencify.ts',
|
||||
'!src/document/node/exclusive-group.ts',
|
||||
'!src/document/node/props/value-to-source.ts',
|
||||
'!src/builtin-simulator/live-editing/live-editing.ts',
|
||||
'!src/designer/offset-observer.ts',
|
||||
'!src/designer/clipboard.ts',
|
||||
'!**/node_modules/**',
|
||||
'!**/vendor/**',
|
||||
],
|
||||
};
|
||||
|
||||
// 只对本仓库内的 pkg 做 mapping
|
||||
jestConfig.moduleNameMapper = {};
|
||||
jestConfig.moduleNameMapper[`^@alilc/lowcode\\-(${pkgNames.join('|')})$`] = '<rootDir>/../$1/src';
|
||||
|
||||
module.exports = jestConfig;
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-renderer-core",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "renderer core",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
@ -10,13 +10,14 @@
|
||||
"es"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "build-scripts build --skip-demo",
|
||||
"test": "build-scripts test --config build.test.json",
|
||||
"build": "build-scripts build --skip-demo"
|
||||
"test:cov": "build-scripts test --config build.test.json --jest-coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-datasource-engine": "^1.0.0",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^4.1.1",
|
||||
"fetch-jsonp": "^1.1.3",
|
||||
@ -33,19 +34,23 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@alilc/lowcode-designer": "1.0.6",
|
||||
"@alilc/lowcode-test-mate": "^1.0.1",
|
||||
"@babel/plugin-transform-typescript": "^7.16.8",
|
||||
"@testing-library/react": "^11.2.2",
|
||||
"@types/classnames": "^2.2.11",
|
||||
"@types/debug": "^4.1.5",
|
||||
"@types/jest": "^26.0.16",
|
||||
"@types/lodash": "^4.14.167",
|
||||
"@types/node": "^13.7.1",
|
||||
"@types/prop-types": "^15.7.3",
|
||||
"@types/react-test-renderer": "^17.0.1",
|
||||
"@types/serialize-javascript": "^5.0.0",
|
||||
"babel-jest": "^27.4.6",
|
||||
"babel-jest": "^26.5.2",
|
||||
"build-plugin-component": "^0.2.11",
|
||||
"jest": "^27.4.7",
|
||||
"jest": "^26.6.3",
|
||||
"react-test-renderer": "^17.0.2",
|
||||
"ts-jest": "^27.1.3"
|
||||
"ts-jest": "^26.5.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import baseRendererFactory from './base';
|
||||
import { isEmpty, goldlog } from '../utils';
|
||||
import { isEmpty } from '../utils';
|
||||
import { IRendererAppHelper, IBaseRendererProps, IBaseRenderComponent } from '../types';
|
||||
|
||||
export default function addonRendererFactory(): IBaseRenderComponent {
|
||||
@ -57,21 +57,6 @@ export default function addonRendererFactory(): IBaseRenderComponent {
|
||||
}
|
||||
}
|
||||
|
||||
goldlog = (goKey: string, params: any) => {
|
||||
const { addonKey, addonConfig = {} } = this.props.config || {};
|
||||
goldlog(
|
||||
goKey,
|
||||
{
|
||||
addonKey,
|
||||
package: addonConfig.package,
|
||||
version: addonConfig.version,
|
||||
...this.appHelper.logParams,
|
||||
...params,
|
||||
},
|
||||
'addon',
|
||||
);
|
||||
};
|
||||
|
||||
get utils() {
|
||||
const { utils = {} } = this.context.config || {};
|
||||
return { ...this.appHelper.utils, ...utils };
|
||||
|
||||
@ -463,8 +463,14 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
|
||||
if (!Comp) {
|
||||
console.error(`${schema.componentName} component is not found in components list! component list is:`, components || this.props.__container?.components);
|
||||
Comp = engine.getNotFoundComponent();
|
||||
otherProps.__componentName = schema.componentName;
|
||||
return engine.createElement(
|
||||
engine.getNotFoundComponent(),
|
||||
{
|
||||
componentName: schema.componentName,
|
||||
componentId: schema.id,
|
||||
},
|
||||
this.__getSchemaChildrenVirtualDom(schema, scope, Comp),
|
||||
);
|
||||
}
|
||||
|
||||
// DesignMode 为 design 情况下,需要进入 leaf Hoc,进行相关事件注册
|
||||
@ -930,7 +936,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
|
||||
const buitin = capitalizeFirstLetter(this.__namespace);
|
||||
const componentNames = [buitin, ...extraComponents];
|
||||
return !isSchema(schema, true) || !componentNames.includes(schema?.componentName ?? '');
|
||||
return !isSchema(schema) || !componentNames.includes(schema?.componentName ?? '');
|
||||
};
|
||||
|
||||
get requestHandlersMap() {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import Debug from 'debug';
|
||||
import adapter from '../adapter';
|
||||
import contextFactory from '../context';
|
||||
import { isFileSchema, goldlog, isEmpty } from '../utils';
|
||||
import { isFileSchema, isEmpty } from '../utils';
|
||||
import baseRendererFactory from './base';
|
||||
import divFactory from '../components/Div';
|
||||
import { IGeneralConstructor, IRenderComponent, IRendererProps, IRendererState } from '../types';
|
||||
@ -71,14 +71,6 @@ export default function rendererFactory(): IRenderComponent {
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
goldlog(
|
||||
'EXP',
|
||||
{
|
||||
action: 'appear',
|
||||
value: !!this.props.designMode,
|
||||
},
|
||||
'renderer',
|
||||
);
|
||||
debug(`entry.componentDidMount - ${this.props.schema && this.props.schema.componentName}`);
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,8 @@ import type { ComponentLifecycle, CSSProperties } from 'react';
|
||||
import { BuiltinSimulatorHost } from '@alilc/lowcode-designer';
|
||||
import { RequestHandler, NodeSchema, NodeData, RootSchema, JSONObject } from '@alilc/lowcode-types';
|
||||
|
||||
export type ISchema = NodeSchema | RootSchema;
|
||||
|
||||
/*
|
||||
** Duck typed component type supporting both react and rax
|
||||
*/
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-console */
|
||||
/* eslint-disable no-new-func */
|
||||
import Debug from 'debug';
|
||||
import { isI18nData, RootSchema, NodeSchema, isJSExpression, JSSlot } from '@alilc/lowcode-types';
|
||||
@ -35,35 +36,53 @@ const EXPRESSION_TYPE = {
|
||||
I18N: 'i18n',
|
||||
};
|
||||
|
||||
const hasSymbol = typeof Symbol === 'function' && Symbol.for;
|
||||
const REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
|
||||
const debug = Debug('utils:index');
|
||||
|
||||
const ENV = {
|
||||
TBE: 'TBE',
|
||||
WEBIDE: 'WEB-IDE',
|
||||
VSCODE: 'VSCODE',
|
||||
WEB: 'WEB',
|
||||
};
|
||||
/**
|
||||
* check if schema passed in is a valid schema
|
||||
* @name isSchema
|
||||
* @returns boolean
|
||||
*/
|
||||
export function isSchema(schema: any): schema is NodeSchema {
|
||||
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((item) => isSchema(item));
|
||||
}
|
||||
// check if props is valid
|
||||
const isValidProps = (props: any) => {
|
||||
if (!props) {
|
||||
return false;
|
||||
}
|
||||
if (isJSExpression(props)) {
|
||||
return true;
|
||||
}
|
||||
return (typeof schema.props === 'object' && !Array.isArray(props));
|
||||
};
|
||||
return !!(schema.componentName && isValidProps(schema.props));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name isSchema
|
||||
* @description 判断是否是模型结构
|
||||
* check if schema passed in is a container type, including : Component Block Page
|
||||
* @param schema
|
||||
* @returns boolean
|
||||
*/
|
||||
export function isSchema(schema: any, ignoreArr = false): schema is NodeSchema {
|
||||
if (isEmpty(schema)) return false;
|
||||
// Leaf 组件也返回 true
|
||||
if (schema.componentName === 'Leaf' || schema.componentName === 'Slot') return true;
|
||||
if (!ignoreArr && Array.isArray(schema)) return schema.every((item) => isSchema(item));
|
||||
return !!(schema.componentName && schema.props && (typeof schema.props === 'object' || isJSExpression(schema.props)));
|
||||
}
|
||||
|
||||
export function isFileSchema(schema: NodeSchema): schema is RootSchema {
|
||||
if (isEmpty(schema)) return false;
|
||||
return ['Page', 'Block', 'Component', 'Addon', 'Temp'].includes(schema.componentName);
|
||||
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;
|
||||
@ -72,8 +91,15 @@ export function inSameDomain() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get css styled name from schema`s fileName
|
||||
* FileName -> lce-file-name
|
||||
* @returns string
|
||||
*/
|
||||
export function getFileCssName(fileName: string) {
|
||||
if (!fileName) return;
|
||||
if (!fileName) {
|
||||
return;
|
||||
}
|
||||
const name = fileName.replace(/([A-Z])/g, '-$1').toLowerCase();
|
||||
return (`lce-${name}`)
|
||||
.split('-')
|
||||
@ -81,79 +107,45 @@ export function getFileCssName(fileName: string) {
|
||||
.join('-');
|
||||
}
|
||||
|
||||
// 兼容乐高设计态 JSBlock 的老协议
|
||||
/**
|
||||
* check if a object is type of JSSlot
|
||||
* @returns string
|
||||
*/
|
||||
export function isJSSlot(obj: any): obj is JSSlot {
|
||||
return obj && typeof obj === 'object' && ([EXPRESSION_TYPE.JSSLOT, EXPRESSION_TYPE.JSBLOCK].includes(obj.type));
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name wait
|
||||
* @description 等待函数
|
||||
* get value from an object
|
||||
* @returns string
|
||||
*/
|
||||
export function wait(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(() => resolve(true), ms));
|
||||
}
|
||||
|
||||
export function curry(Comp: any, hocs = []) {
|
||||
return hocs.reverse().reduce((pre, cur: (pre: any) => any) => {
|
||||
return cur(pre);
|
||||
}, Comp);
|
||||
}
|
||||
|
||||
export function getValue(obj: any, path: string, defaultValue = {}) {
|
||||
if (isEmpty(obj) || typeof obj !== 'object') return defaultValue;
|
||||
// array is not valid type, return default value
|
||||
if (Array.isArray(obj)) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (isEmpty(obj) || typeof obj !== 'object') {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
const res = path.split('.').reduce((pre, cur) => {
|
||||
return pre && pre[cur];
|
||||
}, obj);
|
||||
if (res === undefined) return defaultValue;
|
||||
if (res === undefined) {
|
||||
return defaultValue;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 更新obj的内容但不改变obj的指针
|
||||
export function fillObj(receiver: any = {}, ...suppliers: any) {
|
||||
Object.keys(receiver).forEach((item) => {
|
||||
delete receiver[item];
|
||||
});
|
||||
Object.assign(receiver, ...suppliers);
|
||||
return receiver;
|
||||
}
|
||||
|
||||
// 中划线转驼峰
|
||||
export function toHump(name: string) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
return name.replace(/\-(\w)/g, (_: any, letter: string) => {
|
||||
return letter.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
// 驼峰转中划线
|
||||
export function toLine(name: string) {
|
||||
return name.replace(/([A-Z])/g, '-$1').toLowerCase();
|
||||
}
|
||||
|
||||
// 获取当前环境
|
||||
export function getEnv() {
|
||||
const { userAgent } = navigator;
|
||||
const isVscode = /Electron\//.test(userAgent);
|
||||
if (isVscode) return ENV.VSCODE;
|
||||
const isTheia = (window as any).is_theia === true;
|
||||
if (isTheia) return ENV.WEBIDE;
|
||||
return ENV.WEB;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于构造国际化字符串处理函数
|
||||
* @param {*} locale 国际化标识,例如 zh-CN、en-US
|
||||
* @param {*} messages 国际化语言包
|
||||
*/
|
||||
export function generateI18n(locale = 'zh-CN', messages: any = {}) {
|
||||
return (key: string, values = {}) => {
|
||||
if (!messages || !messages[key]) return '';
|
||||
const formater = new IntlMessageFormat(messages[key], locale);
|
||||
return formater.format(values);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于处理国际化字符串
|
||||
* @param {*} key 语料标识
|
||||
@ -162,7 +154,9 @@ export function generateI18n(locale = 'zh-CN', messages: any = {}) {
|
||||
* @param {*} messages 国际化语言包
|
||||
*/
|
||||
export function getI18n(key: string, values = {}, locale = 'zh-CN', messages: Record<string, any> = {}) {
|
||||
if (!messages || !messages[locale] || !messages[locale][key]) return '';
|
||||
if (!messages || !messages[locale] || !messages[locale][key]) {
|
||||
return '';
|
||||
}
|
||||
const formater = new IntlMessageFormat(messages[locale][key], locale);
|
||||
return formater.format(values);
|
||||
}
|
||||
@ -172,107 +166,46 @@ export function getI18n(key: string, values = {}, locale = 'zh-CN', messages: Re
|
||||
* @param {*} Comp 需要判断的组件
|
||||
*/
|
||||
export function canAcceptsRef(Comp: any) {
|
||||
const hasSymbol = typeof Symbol === 'function' && Symbol.for;
|
||||
const REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
|
||||
// eslint-disable-next-line max-len
|
||||
return Comp?.$$typeof === REACT_FORWARD_REF_TYPE || Comp?.prototype?.isReactComponent || Comp?.prototype?.setState || Comp._forwardRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* 黄金令箭埋点
|
||||
* @param {String} gmKey 为黄金令箭业务类型
|
||||
* @param {Object} params 参数
|
||||
* @param {String} logKey 属性串
|
||||
* 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 goldlog(gmKey: string, params = {}, logKey = 'other') {
|
||||
// vscode 黄金令箭API
|
||||
const sendIDEMessage = (window as any).sendIDEMessage || (inSameDomain() && (window.parent as any).sendIDEMessage);
|
||||
const goKey = serializeParams({
|
||||
sdkVersion: pkg.version,
|
||||
env: getEnv(),
|
||||
...params,
|
||||
});
|
||||
if (sendIDEMessage) {
|
||||
sendIDEMessage({
|
||||
action: 'goldlog',
|
||||
data: {
|
||||
logKey: `/lce.core.${logKey}`,
|
||||
gmKey,
|
||||
goKey,
|
||||
},
|
||||
});
|
||||
}
|
||||
(window as any)?.goldlog?.record(`/lce.core.${logKey}`, gmKey, goKey, 'POST');
|
||||
}
|
||||
|
||||
// utils为编辑器打包生成的utils文件内容,utilsConfig为数据库存放的utils配置
|
||||
export function generateUtils(utils: any, utilsConfig: Array<{ name: string; type: string; content: any }>) {
|
||||
if (!Array.isArray(utilsConfig)) return { ...utils };
|
||||
const res: any = {};
|
||||
utilsConfig.forEach((item) => {
|
||||
if (!item.name || !item.type || !item.content) return;
|
||||
if (item.type === 'function' && typeof item.content === 'function') {
|
||||
res[item.name] = item.content;
|
||||
} else if (item.type === 'npm' && utils[item.name]) {
|
||||
res[item.name] = utils[item.name];
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
// 将函数返回结果转成promise形式,如果函数有返回值则根据返回值的bool类型判断是reject还是resolve,若函数无返回值默认执行resolve
|
||||
export function transformToPromise(input: any) {
|
||||
if (input instanceof Promise) return input;
|
||||
return new Promise((resolve, reject) => {
|
||||
if (input || input === undefined) {
|
||||
resolve({});
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function moveArrayItem(arr: any[], sourceIdx: number, distIdx: number, direction: 'after' | 'before') {
|
||||
if (
|
||||
!Array.isArray(arr) ||
|
||||
sourceIdx === distIdx ||
|
||||
sourceIdx < 0 ||
|
||||
sourceIdx >= arr.length ||
|
||||
distIdx < 0 ||
|
||||
distIdx >= arr.length
|
||||
) return arr;
|
||||
const item = arr[sourceIdx];
|
||||
if (direction === 'after') {
|
||||
arr.splice(distIdx + 1, 0, item);
|
||||
} else {
|
||||
arr.splice(distIdx, 0, item);
|
||||
}
|
||||
if (sourceIdx < distIdx) {
|
||||
arr.splice(sourceIdx, 1);
|
||||
} else {
|
||||
arr.splice(sourceIdx + 1, 1);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
export function transformArrayToMap(arr: any[], key: string, overwrite = true) {
|
||||
if (isEmpty(arr) || !Array.isArray(arr)) return {};
|
||||
if (isEmpty(arr) || !Array.isArray(arr)) {
|
||||
return {};
|
||||
}
|
||||
const res: any = {};
|
||||
arr.forEach((item) => {
|
||||
const curKey = item[key];
|
||||
if (item[key] === undefined) return;
|
||||
if (res[curKey] && !overwrite) return;
|
||||
if (item[key] === undefined) {
|
||||
return;
|
||||
}
|
||||
if (res[curKey] && !overwrite) {
|
||||
return;
|
||||
}
|
||||
res[curKey] = item;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
export function checkPropTypes(value: any, name: string, rule: any, componentName: string) {
|
||||
let ruleFunction = rule;
|
||||
if (typeof rule === 'string') {
|
||||
rule = new Function(`"use strict"; const PropTypes = arguments[0]; return ${rule}`)(PropTypes2);
|
||||
ruleFunction = new Function(`"use strict"; const PropTypes = arguments[0]; return ${rule}`)(PropTypes2);
|
||||
}
|
||||
if (!rule || typeof rule !== 'function') {
|
||||
if (!ruleFunction || typeof ruleFunction !== 'function') {
|
||||
console.warn('checkPropTypes should have a function type rule argument');
|
||||
return true;
|
||||
}
|
||||
const err = rule(
|
||||
const err = ruleFunction(
|
||||
{
|
||||
[name]: value,
|
||||
},
|
||||
@ -288,62 +221,16 @@ export function checkPropTypes(value: any, name: string, rule: any, componentNam
|
||||
return !err;
|
||||
}
|
||||
|
||||
export function transformSchemaToPure(obj: any) {
|
||||
const pureObj = (obj: any): any => {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item) => pureObj(item));
|
||||
} else if (typeof obj === 'object') {
|
||||
// 对于undefined及null直接返回
|
||||
if (!obj) return obj;
|
||||
const res: any = {};
|
||||
forEach(obj, (val: any, key: string) => {
|
||||
if (key.startsWith('__') && key !== '__ignoreParse') return;
|
||||
res[key] = pureObj(val);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
return pureObj(obj);
|
||||
}
|
||||
|
||||
export function transformSchemaToStandard(obj: any) {
|
||||
const standardObj = (obj: any): any => {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item) => standardObj(item));
|
||||
} else if (typeof obj === 'object') {
|
||||
// 对于undefined及null直接返回
|
||||
if (!obj) return obj;
|
||||
const res: any = {};
|
||||
forEach(obj, (val: any, key: string) => {
|
||||
if (key.startsWith('__') && key !== '__ignoreParse') return;
|
||||
if (isSchema(val) && key !== 'children' && obj.type !== 'JSSlot') {
|
||||
res[key] = {
|
||||
type: 'JSSlot',
|
||||
value: standardObj(val),
|
||||
};
|
||||
// table特殊处理
|
||||
if (key === 'cell') {
|
||||
res[key].params = ['value', 'index', 'record'];
|
||||
}
|
||||
} else {
|
||||
res[key] = standardObj(val);
|
||||
}
|
||||
});
|
||||
return res;
|
||||
} else if (typeof obj === 'function') {
|
||||
return {
|
||||
type: 'JSFunction',
|
||||
value: obj.toString(),
|
||||
};
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
return standardObj(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* transform string to a function
|
||||
* @param str function in string form
|
||||
* @returns funtion
|
||||
*/
|
||||
export function transformStringToFunction(str: string) {
|
||||
if (typeof str !== 'string') return str;
|
||||
if (typeof str !== 'string') {
|
||||
return str;
|
||||
}
|
||||
if (inSameDomain() && (window.parent as any).__newFunc) {
|
||||
return (window.parent as any).__newFunc(`"use strict"; return ${str}`)();
|
||||
} else {
|
||||
@ -351,6 +238,96 @@ export function transformStringToFunction(str: string) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象类型JSExpression,支持省略this
|
||||
* @param str expression in string form
|
||||
* @param self scope object
|
||||
* @returns funtion
|
||||
*/
|
||||
export function parseExpression(str: any, self: any) {
|
||||
try {
|
||||
const contextArr = ['"use strict";', 'var __self = arguments[0];'];
|
||||
contextArr.push('return ');
|
||||
let tarStr: string;
|
||||
|
||||
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, (_a: any, b: any) => `__self${b}`);
|
||||
tarStr = contextArr.join('\n') + tarStr;
|
||||
|
||||
// 默认调用顶层窗口的parseObj, 保障new Function的window对象是顶层的window对象
|
||||
if (inSameDomain() && (window.parent as any).__newFunc) {
|
||||
return (window.parent as any).__newFunc(tarStr)(self);
|
||||
}
|
||||
const code = `with($scope || {}) { ${tarStr} }`;
|
||||
return new Function('$scope', code)(self);
|
||||
} catch (err) {
|
||||
debug('parseExpression.error', err, str, self);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* capitalize first letter
|
||||
* @param word string to be proccessed
|
||||
* @returns string capitalized string
|
||||
*/
|
||||
export function capitalizeFirstLetter(word: string) {
|
||||
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: any): boolean {
|
||||
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: any) {
|
||||
if (!obj || Array.isArray(obj)) {
|
||||
return false;
|
||||
}
|
||||
return typeof obj === 'object' && obj?.type === 'variable';
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 i18n 结构,降级解释为对 i18n 接口的调用
|
||||
* @param i18nInfo object
|
||||
* @param self context
|
||||
*/
|
||||
export function parseI18n(i18nInfo: any, self: any) {
|
||||
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: any, fn: any, context?: any) {
|
||||
if (!targetObj || Array.isArray(targetObj) || isString(targetObj) || typeof targetObj !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(targetObj).forEach((key) => fn.call(context, targetObj[key], key));
|
||||
}
|
||||
|
||||
export function parseData(schema: unknown, self: any): any {
|
||||
if (isJSExpression(schema)) {
|
||||
return parseExpression(schema, self);
|
||||
@ -364,10 +341,14 @@ export function parseData(schema: unknown, self: any): any {
|
||||
return schema.bind(self);
|
||||
} else if (typeof schema === 'object') {
|
||||
// 对于undefined及null直接返回
|
||||
if (!schema) return schema;
|
||||
if (!schema) {
|
||||
return schema;
|
||||
}
|
||||
const res: any = {};
|
||||
forEach(schema, (val: any, key: string) => {
|
||||
if (key.startsWith('__')) return;
|
||||
if (key.startsWith('__')) {
|
||||
return;
|
||||
}
|
||||
res[key] = parseData(val, self);
|
||||
});
|
||||
return res;
|
||||
@ -375,79 +356,22 @@ export function parseData(schema: unknown, self: any): any {
|
||||
return schema;
|
||||
}
|
||||
|
||||
/* 全匹配{{开头,}}结尾的变量表达式,或者对象类型JSExpression,支持省略this */
|
||||
export function parseExpression(str: any, self: any) {
|
||||
try {
|
||||
const contextArr = ['"use strict";', 'var __self = arguments[0];'];
|
||||
contextArr.push('return ');
|
||||
let tarStr;
|
||||
|
||||
tarStr = (str.value || '').trim();
|
||||
tarStr = tarStr.replace(/this(\W|$)/g, (_a: any, b: any) => `__self${b}`);
|
||||
tarStr = contextArr.join('\n') + tarStr;
|
||||
// 默认调用顶层窗口的parseObj,保障new Function的window对象是顶层的window对象
|
||||
if (inSameDomain() && (window.parent as any).__newFunc) {
|
||||
return (window.parent as any).__newFunc(tarStr)(self);
|
||||
}
|
||||
const code = `with($scope || {}) { ${tarStr} }`;
|
||||
return new Function('$scope', code)(self);
|
||||
} catch (err) {
|
||||
debug('parseExpression.error', err, str, self);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// 首字母大写
|
||||
export function capitalizeFirstLetter(word: string) {
|
||||
return word[0].toUpperCase() + word.slice(1);
|
||||
}
|
||||
|
||||
export function isVariable(obj: any) {
|
||||
return obj && typeof obj === 'object' && obj?.type === 'variable';
|
||||
}
|
||||
|
||||
/* 将 i18n 结构,降级解释为对 i18n 接口的调用 */
|
||||
export function parseI18n(i18nInfo: any, self: any) {
|
||||
return parseExpression({
|
||||
type: EXPRESSION_TYPE.JSEXPRESSION,
|
||||
value: `this.i18n('${i18nInfo.key}')`,
|
||||
}, self);
|
||||
}
|
||||
|
||||
export function forEach(obj: any, fn: any, context?: any) {
|
||||
obj = obj || {};
|
||||
Object.keys(obj).forEach(key => fn.call(context, obj[key], key));
|
||||
}
|
||||
|
||||
export function shallowEqual(objA: any, objB: any) {
|
||||
if (objA === objB) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const keysA = Object.keys(objA);
|
||||
if (keysA.length !== Object.keys(objB).length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0, key; i < keysA.length; i++) {
|
||||
key = keysA[i];
|
||||
if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* process params for using in a url query
|
||||
* @param obj params to be processed
|
||||
* @returns string
|
||||
*/
|
||||
export function serializeParams(obj: any) {
|
||||
let rst: any = [];
|
||||
let result: any = [];
|
||||
forEach(obj, (val: any, key: any) => {
|
||||
if (val === null || val === undefined || val === '') return;
|
||||
if (typeof val === 'object') rst.push(`${key}=${encodeURIComponent(JSON.stringify(val))}`);
|
||||
else rst.push(`${key}=${encodeURIComponent(val)}`);
|
||||
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 rst.join('&');
|
||||
return result.join('&');
|
||||
}
|
||||
@ -1,280 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`loop schema loop key 1`] = `
|
||||
<div
|
||||
className="lce-page _css_pseudo_node_ocl1djd9o41"
|
||||
style={Object {}}
|
||||
>
|
||||
<div
|
||||
__componentName="RootHeader"
|
||||
__id="node_ocl1djd9o42"
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
<div
|
||||
__componentName="RootContent"
|
||||
__id="node_ocl1djd9o43"
|
||||
contentBgColor="white"
|
||||
contentMargin="20"
|
||||
contentPadding="20"
|
||||
>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o45"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o45"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1n"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o45"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o45"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1n"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o45"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o45"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1n"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
<div
|
||||
__componentName="Div"
|
||||
__id="node_ocl1djd9o46"
|
||||
__style__={Object {}}
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ocl1djd9o46"
|
||||
customClassName=""
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="div_l1djdj1o"
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
__componentName="RootFooter"
|
||||
__id="node_ocl1djd9o44"
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`notFountComponent not found snapshot 1`] = `
|
||||
<div
|
||||
className="lce-page _css_pseudo_node_ockyigdqxl1"
|
||||
style={Object {}}
|
||||
>
|
||||
<div
|
||||
__componentName="RootHeader"
|
||||
__id="node_ockyigdqxl2"
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
<div
|
||||
__componentName="RootContent"
|
||||
__id="node_ockyigdqxl3"
|
||||
contentBgColor="white"
|
||||
contentMargin="20"
|
||||
contentPadding="20"
|
||||
>
|
||||
<div
|
||||
__componentName="Button"
|
||||
__id="node_ockyigdqxl5"
|
||||
__style__={Object {}}
|
||||
baseIcon=""
|
||||
behavior="NORMAL"
|
||||
className="_css_pseudo_node_ockyigdqxl5"
|
||||
content="按 钮"
|
||||
events={
|
||||
Object {
|
||||
"ignored": true,
|
||||
}
|
||||
}
|
||||
fieldId="button_kyige3yf"
|
||||
loading={false}
|
||||
otherIcon=""
|
||||
size="medium"
|
||||
triggerEventsWhenLoading={false}
|
||||
type="primary"
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
__componentName="RootFooter"
|
||||
__id="node_ockyigdqxl4"
|
||||
>
|
||||
Component Not Found
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -1,42 +0,0 @@
|
||||
import renderer from 'react-test-renderer';
|
||||
import React from 'react';
|
||||
import '../utils/react-env-init';
|
||||
import pageRendererFactory from '../../src/renderer/renderer';
|
||||
import { sampleSchema } from '../mock/sample';
|
||||
import loopSchema from '../mock/loop';
|
||||
|
||||
describe('notFountComponent', () => {
|
||||
const Render = pageRendererFactory();
|
||||
|
||||
const component = renderer.create(
|
||||
// @ts-ignore
|
||||
<Render
|
||||
schema={sampleSchema as any}
|
||||
components={{}}
|
||||
appHelper={{}}
|
||||
/>,
|
||||
);
|
||||
|
||||
it('not found snapshot', () => {
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('loop schema', () => {
|
||||
it('loop key', () => {
|
||||
const Render = pageRendererFactory();
|
||||
|
||||
const component = renderer.create(
|
||||
// @ts-ignore
|
||||
<Render
|
||||
schema={loopSchema as any}
|
||||
components={{}}
|
||||
appHelper={{}}
|
||||
/>,
|
||||
);
|
||||
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
})
|
||||
})
|
||||
567
packages/renderer-core/tests/fixtures/schema/basic.ts
vendored
Normal file
567
packages/renderer-core/tests/fixtures/schema/basic.ts
vendored
Normal file
@ -0,0 +1,567 @@
|
||||
export default {
|
||||
componentName: 'Page',
|
||||
id: 'node_dockcviv8fo1',
|
||||
props: {
|
||||
ref: 'outterView',
|
||||
autoLoading: true,
|
||||
style: {
|
||||
padding: '0 5px 0 5px',
|
||||
},
|
||||
},
|
||||
fileName: 'test',
|
||||
dataSource: {
|
||||
list: [],
|
||||
},
|
||||
state: {
|
||||
text: 'outter',
|
||||
isShowDialog: false,
|
||||
},
|
||||
css: 'body {font-size: 12px;} .botton{width:100px;color:#ff00ff}',
|
||||
lifeCycles: {
|
||||
componentDidMount: {
|
||||
type: 'JSFunction',
|
||||
value: "function() {\n console.log('did mount');\n }",
|
||||
},
|
||||
componentWillUnmount: {
|
||||
type: 'JSFunction',
|
||||
value: "function() {\n console.log('will umount');\n }",
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
testFunc: {
|
||||
type: 'JSFunction',
|
||||
value: "function() {\n console.log('test func');\n }",
|
||||
},
|
||||
onClick: {
|
||||
type: 'JSFunction',
|
||||
value: 'function() {\n this.setState({\n isShowDialog: true\n })\n }',
|
||||
},
|
||||
closeDialog: {
|
||||
type: 'JSFunction',
|
||||
value: 'function() {\n this.setState({\n isShowDialog: false\n })\n }',
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Box',
|
||||
id: 'node_dockcy8n9xed',
|
||||
props: {
|
||||
style: {
|
||||
backgroundColor: 'rgba(31,56,88,0.1)',
|
||||
padding: '12px 12px 12px 12px',
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Box',
|
||||
id: 'node_dockcy8n9xee',
|
||||
props: {
|
||||
style: {
|
||||
padding: '12px 12px 12px 12px',
|
||||
backgroundColor: '#ffffff',
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Breadcrumb',
|
||||
id: 'node_dockcy8n9xef',
|
||||
props: {
|
||||
prefix: 'next-',
|
||||
maxNode: 100,
|
||||
component: 'nav',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Breadcrumb.Item',
|
||||
id: 'node_dockcy8n9xeg',
|
||||
props: {
|
||||
prefix: 'next-',
|
||||
children: '首页',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Breadcrumb.Item',
|
||||
id: 'node_dockcy8n9xei',
|
||||
props: {
|
||||
prefix: 'next-',
|
||||
children: '品质中台',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Breadcrumb.Item',
|
||||
id: 'node_dockcy8n9xek',
|
||||
props: {
|
||||
prefix: 'next-',
|
||||
children: '商家品质页面管理',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Breadcrumb.Item',
|
||||
id: 'node_dockcy8n9xem',
|
||||
props: {
|
||||
prefix: 'next-',
|
||||
children: '质检知识条配置',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Box',
|
||||
id: 'node_dockcy8n9xeo',
|
||||
props: {
|
||||
style: {
|
||||
marginTop: '12px',
|
||||
backgroundColor: '#ffffff',
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Form',
|
||||
id: 'node_dockcy8n9xep',
|
||||
props: {
|
||||
inline: true,
|
||||
style: {
|
||||
marginTop: '12px',
|
||||
marginRight: '12px',
|
||||
marginLeft: '12px',
|
||||
},
|
||||
__events: [],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_dockcy8n9xeq',
|
||||
props: {
|
||||
style: {
|
||||
marginBottom: '0',
|
||||
},
|
||||
label: '类目名:',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Select',
|
||||
id: 'node_dockcy8n9xer',
|
||||
props: {
|
||||
mode: 'single',
|
||||
hasArrow: true,
|
||||
cacheValue: true,
|
||||
style: {
|
||||
width: '150px',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_dockcy8n9xes',
|
||||
props: {
|
||||
style: {
|
||||
marginBottom: '0',
|
||||
},
|
||||
label: '项目类型:',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Select',
|
||||
id: 'node_dockcy8n9xet',
|
||||
props: {
|
||||
mode: 'single',
|
||||
hasArrow: true,
|
||||
cacheValue: true,
|
||||
style: {
|
||||
width: '200px',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_dockcy8n9xeu',
|
||||
props: {
|
||||
style: {
|
||||
marginBottom: '0',
|
||||
},
|
||||
label: '项目 ID:',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Input',
|
||||
id: 'node_dockcy8n9xev',
|
||||
props: {
|
||||
hasBorder: true,
|
||||
size: 'medium',
|
||||
autoComplete: 'off',
|
||||
style: {
|
||||
width: '200px',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Button.Group',
|
||||
id: 'node_dockcy8n9xew',
|
||||
props: {},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Button',
|
||||
id: 'node_dockcy8n9xex',
|
||||
props: {
|
||||
type: 'primary',
|
||||
style: {
|
||||
margin: '0 5px 0 5px',
|
||||
},
|
||||
htmlType: 'submit',
|
||||
children: '搜索',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Button',
|
||||
id: 'node_dockcy8n9xe10',
|
||||
props: {
|
||||
type: 'normal',
|
||||
style: {
|
||||
margin: '0 5px 0 5px',
|
||||
},
|
||||
htmlType: 'reset',
|
||||
children: '清空',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Box',
|
||||
id: 'node_dockcy8n9xe1f',
|
||||
props: {
|
||||
style: {
|
||||
backgroundColor: '#ffffff',
|
||||
paddingBottom: '24px',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Button',
|
||||
id: 'node_dockd5nrh9p4',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'medium',
|
||||
htmlType: 'button',
|
||||
component: 'button',
|
||||
children: '新建配置',
|
||||
style: {},
|
||||
__events: [
|
||||
{
|
||||
type: 'componentEvent',
|
||||
name: 'onClick',
|
||||
relatedEventName: 'onClick',
|
||||
},
|
||||
],
|
||||
onClick: {
|
||||
type: 'JSFunction',
|
||||
value: 'function(){ this.onClick() }',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Box',
|
||||
id: 'node_dockd5nrh9p5',
|
||||
props: {},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Table',
|
||||
id: 'node_dockjielosj1',
|
||||
props: {
|
||||
showMiniPager: true,
|
||||
showActionBar: true,
|
||||
actionBar: [
|
||||
{
|
||||
title: '新增',
|
||||
type: 'primary',
|
||||
},
|
||||
{
|
||||
title: '编辑',
|
||||
},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
dataKey: 'name',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
title: '姓名',
|
||||
editType: 'text',
|
||||
},
|
||||
{
|
||||
dataKey: 'age',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
title: '年龄',
|
||||
},
|
||||
{
|
||||
dataKey: 'email',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
title: '邮箱',
|
||||
},
|
||||
],
|
||||
data: [
|
||||
{
|
||||
name: '王小',
|
||||
id: '1',
|
||||
age: 15000,
|
||||
email: 'aaa@abc.com',
|
||||
},
|
||||
{
|
||||
name: '王中',
|
||||
id: '2',
|
||||
age: 25000,
|
||||
email: 'bbb@abc.com',
|
||||
},
|
||||
{
|
||||
name: '王大',
|
||||
id: '3',
|
||||
age: 35000,
|
||||
email: 'ccc@abc.com',
|
||||
},
|
||||
],
|
||||
actionTitle: '操作',
|
||||
actionWidth: 180,
|
||||
actionType: 'link',
|
||||
actionFixed: 'right',
|
||||
actionHidden: false,
|
||||
maxWebShownActionCount: 2,
|
||||
actionColumn: [
|
||||
{
|
||||
title: '编辑',
|
||||
callback: {
|
||||
type: 'JSFunction',
|
||||
value: '(rowData, action, table) => {\n return table.editRow(rowData).then((row) => {\n console.log(row);\n });\n }',
|
||||
},
|
||||
device: [
|
||||
'desktop',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '保存',
|
||||
callback: {
|
||||
type: 'JSFunction',
|
||||
value: '(rowData, action, table) => { \nreturn table.saveRow(rowData).then((row) => { \nconsole.log(row); \n}); \n}',
|
||||
},
|
||||
mode: 'EDIT',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Box',
|
||||
id: 'node_dockd5nrh9pg',
|
||||
props: {
|
||||
style: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Pagination',
|
||||
id: 'node_dockd5nrh9pf',
|
||||
props: {
|
||||
prefix: 'next-',
|
||||
type: 'normal',
|
||||
shape: 'normal',
|
||||
size: 'medium',
|
||||
defaultCurrent: 1,
|
||||
total: 100,
|
||||
pageShowCount: 5,
|
||||
pageSize: 10,
|
||||
pageSizePosition: 'start',
|
||||
showJump: true,
|
||||
style: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Dialog',
|
||||
id: 'node_dockcy8n9xe1h',
|
||||
props: {
|
||||
prefix: 'next-',
|
||||
footerAlign: 'right',
|
||||
footerActions: [
|
||||
'ok',
|
||||
'cancel',
|
||||
],
|
||||
closeable: 'esc,close',
|
||||
hasMask: true,
|
||||
align: 'cc cc',
|
||||
minMargin: 40,
|
||||
visible: {
|
||||
type: 'JSExpression',
|
||||
value: 'this.state.isShowDialog',
|
||||
},
|
||||
title: '标题',
|
||||
events: [],
|
||||
__events: [
|
||||
{
|
||||
type: 'componentEvent',
|
||||
name: 'onCancel',
|
||||
relatedEventName: 'closeDialog',
|
||||
},
|
||||
{
|
||||
type: 'componentEvent',
|
||||
name: 'onClose',
|
||||
relatedEventName: 'closeDialog',
|
||||
},
|
||||
{
|
||||
type: 'componentEvent',
|
||||
name: 'onOk',
|
||||
relatedEventName: 'testFunc',
|
||||
},
|
||||
],
|
||||
onCancel: {
|
||||
type: 'JSFunction',
|
||||
value: 'function(){ this.closeDialog() }',
|
||||
},
|
||||
onClose: {
|
||||
type: 'JSFunction',
|
||||
value: 'function(){ this.closeDialog() }',
|
||||
},
|
||||
onOk: {
|
||||
type: 'JSFunction',
|
||||
value: 'function(){ this.testFunc() }',
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Form',
|
||||
id: 'node_dockd5nrh9pi',
|
||||
props: {
|
||||
inline: false,
|
||||
labelAlign: 'top',
|
||||
labelTextAlign: 'right',
|
||||
size: 'medium',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_dockd5nrh9pj',
|
||||
props: {
|
||||
style: {
|
||||
marginBottom: '0',
|
||||
minWidth: '200px',
|
||||
minHeight: '28px',
|
||||
},
|
||||
label: '商品类目',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Select',
|
||||
id: 'node_dockd5nrh9pk',
|
||||
props: {
|
||||
mode: 'single',
|
||||
hasArrow: true,
|
||||
cacheValue: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_dockd5nrh9pl',
|
||||
props: {
|
||||
style: {
|
||||
marginBottom: '0',
|
||||
minWidth: '200px',
|
||||
minHeight: '28px',
|
||||
},
|
||||
label: '商品类目',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Select',
|
||||
id: 'node_dockd5nrh9pm',
|
||||
props: {
|
||||
mode: 'single',
|
||||
hasArrow: true,
|
||||
cacheValue: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_dockd5nrh9pn',
|
||||
props: {
|
||||
style: {
|
||||
marginBottom: '0',
|
||||
minWidth: '200px',
|
||||
minHeight: '28px',
|
||||
},
|
||||
label: '商品类目',
|
||||
asterisk: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Select',
|
||||
id: 'node_dockd5nrh9po',
|
||||
props: {
|
||||
mode: 'single',
|
||||
hasArrow: true,
|
||||
cacheValue: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'Form.Item',
|
||||
id: 'node_dockd5nrh9pp',
|
||||
props: {
|
||||
style: {
|
||||
marginBottom: '0',
|
||||
minWidth: '200px',
|
||||
minHeight: '28px',
|
||||
},
|
||||
label: '商品类目',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: 'Input',
|
||||
id: 'node_dockd5nrh9pr',
|
||||
props: {
|
||||
hasBorder: true,
|
||||
size: 'medium',
|
||||
autoComplete: 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
componentName: 'ErrorComponent',
|
||||
id: 'node_dockd5nrh9pr',
|
||||
props: {
|
||||
name: 'error',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
7
packages/renderer-core/tests/fixtures/unhandled-rejection.ts
vendored
Normal file
7
packages/renderer-core/tests/fixtures/unhandled-rejection.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
if (!process.env.LISTENING_TO_UNHANDLED_REJECTION) {
|
||||
process.on('unhandledRejection', reason => {
|
||||
throw reason;
|
||||
});
|
||||
// Avoid memory leak by adding too many listeners
|
||||
process.env.LISTENING_TO_UNHANDLED_REJECTION = 'true';
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
324
packages/renderer-core/tests/renderer/renderer.test.tsx
Normal file
324
packages/renderer-core/tests/renderer/renderer.test.tsx
Normal file
@ -0,0 +1,324 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import schema from '../fixtures/schema/basic';
|
||||
import '../utils/react-env-init';
|
||||
import rendererFactory from '../../src/renderer/renderer';
|
||||
import components from '../utils/components';
|
||||
|
||||
const Renderer = rendererFactory();
|
||||
|
||||
function getComp(schema, comp = null): Promise<{
|
||||
component,
|
||||
inst,
|
||||
}> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const component = renderer.create(
|
||||
// @ts-ignore
|
||||
<Renderer
|
||||
schema={schema}
|
||||
components={components as any}
|
||||
/>);
|
||||
|
||||
const componentInstance = component.root;
|
||||
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
inst: comp ? componentInstance.findAllByType(comp) : null,
|
||||
component,
|
||||
});
|
||||
}, 20);
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
});
|
||||
|
||||
let componentSnapshot;
|
||||
|
||||
afterEach(() => {
|
||||
if (componentSnapshot) {
|
||||
let tree = componentSnapshot.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
componentSnapshot = null;
|
||||
}
|
||||
});
|
||||
|
||||
describe('Base Render', () => {
|
||||
it('renderComp', () => {
|
||||
const content = (
|
||||
// @ts-ignore
|
||||
<Renderer
|
||||
schema={schema as any}
|
||||
components={components as any}
|
||||
/>);
|
||||
const tree = renderer.create(content).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('JSExpression', () => {
|
||||
it('base props', (done) => {
|
||||
const schema = {
|
||||
componentName: 'Page',
|
||||
props: {},
|
||||
children: [
|
||||
{
|
||||
componentName: "Div",
|
||||
props: {
|
||||
className: 'div-ut',
|
||||
text: "123",
|
||||
visible: true,
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||
expect(inst[0].props.text).toBe('123');
|
||||
expect(inst[0].props.visible).toBeTruthy();
|
||||
|
||||
componentSnapshot = component;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('JSExpression props', (done) => {
|
||||
const schema = {
|
||||
componentName: 'Page',
|
||||
props: {},
|
||||
state: {
|
||||
isShowDialog: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: "Div",
|
||||
props: {
|
||||
className: "div-ut",
|
||||
visible: {
|
||||
type: 'JSExpression',
|
||||
value: 'this.state.isShowDialog',
|
||||
},
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||
expect(inst[0].props.visible).toBeTruthy();
|
||||
componentSnapshot = component;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('JSExpression props with loop', (done) => {
|
||||
const schema = {
|
||||
componentName: 'Page',
|
||||
props: {},
|
||||
state: {
|
||||
isShowDialog: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: "Div",
|
||||
loop: [
|
||||
{
|
||||
name: '1',
|
||||
},
|
||||
{
|
||||
name: '2'
|
||||
}
|
||||
],
|
||||
props: {
|
||||
className: "div-ut",
|
||||
name1: {
|
||||
type: 'JSExpression',
|
||||
value: 'this.item.name',
|
||||
},
|
||||
name2: {
|
||||
type: 'JSExpression',
|
||||
value: 'item.name',
|
||||
},
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||
// expect(inst[0].props.visible).toBeTruthy();
|
||||
expect(inst.length).toEqual(2);
|
||||
[1, 2].forEach((i) => {
|
||||
expect(inst[0].props[`name${i}`]).toBe('1');
|
||||
expect(inst[1].props[`name${i}`]).toBe('2');
|
||||
})
|
||||
componentSnapshot = component;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// it('JSFunction props with loop', (done) => {
|
||||
// const schema = {
|
||||
// componentName: 'Page',
|
||||
// props: {},
|
||||
// state: {
|
||||
// isShowDialog: true,
|
||||
// },
|
||||
// children: [
|
||||
// {
|
||||
// componentName: "Div",
|
||||
// loop: [
|
||||
// {
|
||||
// name: '1',
|
||||
// },
|
||||
// {
|
||||
// name: '2'
|
||||
// }
|
||||
// ],
|
||||
// props: {
|
||||
// className: "div-ut",
|
||||
// onClick1: {
|
||||
// type: 'JSFunction',
|
||||
// value: '() => this.item.name',
|
||||
// },
|
||||
// onClick2: {
|
||||
// type: 'JSFunction',
|
||||
// value: 'function(){ return this.item.name }',
|
||||
// },
|
||||
// onClick3: {
|
||||
// type: 'JSFunction',
|
||||
// value: 'function(){ return item.name }',
|
||||
// },
|
||||
// onClick4: {
|
||||
// type: 'JSFunction',
|
||||
// value: '() => item.name',
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// };
|
||||
|
||||
// getComp(schema, components.Div).then(({ component, inst }) => {
|
||||
// // expect(inst[0].props.visible).toBeTruthy();
|
||||
// expect(inst.length).toEqual(2);
|
||||
// [1, 2, 3, 4].forEach((i) => {
|
||||
// expect(inst[0].props[`onClick${i}`]()).toBe('1');
|
||||
// expect(inst[1].props[`onClick${i}`]()).toBe('2');
|
||||
// })
|
||||
// componentSnapshot = component;
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
|
||||
it('JSFunction props', (done) => {
|
||||
const schema = {
|
||||
componentName: 'Page',
|
||||
props: {},
|
||||
state: {
|
||||
isShowDialog: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
componentName: "Div",
|
||||
props: {
|
||||
className: "div-ut",
|
||||
onClick: {
|
||||
type: 'JSFunction',
|
||||
value: 'function() {return this.state.isShowDialog}',
|
||||
},
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||
expect(!!inst[0].props.onClick).toBeTruthy();
|
||||
expect(inst[0].props.onClick()).toBeTruthy();
|
||||
|
||||
componentSnapshot = component;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('JSSlot has loop', (done) => {
|
||||
const schema = {
|
||||
componentName: "Page",
|
||||
props: {},
|
||||
children: [
|
||||
{
|
||||
componentName: "SlotComponent",
|
||||
id: "node_k8bnubvz",
|
||||
props: {
|
||||
mobileSlot: {
|
||||
type: "JSSlot",
|
||||
title: "mobile容器",
|
||||
name: "mobileSlot",
|
||||
value: [
|
||||
{
|
||||
condition: true,
|
||||
hidden: false,
|
||||
children: [
|
||||
{
|
||||
condition: true,
|
||||
hidden: false,
|
||||
loopArgs: [
|
||||
"item",
|
||||
"index"
|
||||
],
|
||||
isLocked: false,
|
||||
conditionGroup: "",
|
||||
componentName: "Text",
|
||||
id: "node_ocl1ao1o7w4",
|
||||
title: "",
|
||||
props: {
|
||||
maxLine: 0,
|
||||
showTitle: false,
|
||||
className: "text_l1ao7pfb",
|
||||
behavior: "NORMAL",
|
||||
content: "这是一个低代码业务组件~",
|
||||
__style__: ":root {\n font-size: 14px;\n color: #666;\n}",
|
||||
fieldId: "text_l1ao7lvp"
|
||||
}
|
||||
}
|
||||
],
|
||||
loop: {
|
||||
type: "JSExpression",
|
||||
value: "state.content"
|
||||
},
|
||||
loopArgs: [
|
||||
"item",
|
||||
"index"
|
||||
],
|
||||
isLocked: false,
|
||||
conditionGroup: "",
|
||||
componentName: "Div",
|
||||
id: "node_ocl1ao1o7w3",
|
||||
title: "",
|
||||
props: {
|
||||
useFieldIdAsDomId: false,
|
||||
customClassName: "",
|
||||
className: "div_l1ao7pfc",
|
||||
behavior: "NORMAL",
|
||||
__style__: ":root {\n padding: 12px;\n background: #f2f2f2;\n border: 1px solid #ddd;\n}",
|
||||
fieldId: "div_l1ao7lvq"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
state: {
|
||||
content: {
|
||||
type: "JSExpression",
|
||||
value: "[{}, {}, {}]",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
getComp(schema, components.Div).then(({ component, inst }) => {
|
||||
expect(inst.length).toBe(3);
|
||||
componentSnapshot = component;
|
||||
done();
|
||||
});
|
||||
})
|
||||
})
|
||||
12
packages/renderer-core/tests/setup.ts
Normal file
12
packages/renderer-core/tests/setup.ts
Normal file
@ -0,0 +1,12 @@
|
||||
jest.mock('zen-logger', () => {
|
||||
class Logger {
|
||||
log() {}
|
||||
error() {}
|
||||
warn() {}
|
||||
debug() {}
|
||||
}
|
||||
return {
|
||||
__esModule: true,
|
||||
default: Logger,
|
||||
};
|
||||
});
|
||||
426
packages/renderer-core/tests/utils/common.test.ts
Normal file
426
packages/renderer-core/tests/utils/common.test.ts
Normal file
@ -0,0 +1,426 @@
|
||||
// @ts-nocheck
|
||||
import {
|
||||
isSchema,
|
||||
isFileSchema,
|
||||
inSameDomain,
|
||||
getFileCssName,
|
||||
isJSSlot,
|
||||
getValue,
|
||||
getI18n,
|
||||
transformArrayToMap,
|
||||
transformStringToFunction,
|
||||
isVariable,
|
||||
capitalizeFirstLetter,
|
||||
forEach,
|
||||
isString,
|
||||
serializeParams,
|
||||
parseExpression,
|
||||
parseI18n,
|
||||
parseData,
|
||||
} from '../../src/utils/common';
|
||||
|
||||
describe('test isSchema', () => {
|
||||
it('should be false when empty value is passed', () => {
|
||||
expect(isSchema(null)).toBeFalsy();
|
||||
expect(isSchema(undefined)).toBeFalsy();
|
||||
expect(isSchema('')).toBeFalsy();
|
||||
expect(isSchema({})).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should be true when componentName is Leaf or Slot ', () => {
|
||||
expect(isSchema({ componentName: 'Leaf' })).toBeTruthy();
|
||||
expect(isSchema({ componentName: 'Slot' })).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should check each item of an array', () => {
|
||||
const validArraySchema = [
|
||||
{ componentName: 'Button', props: {}},
|
||||
{ componentName: 'Button', props: { type: 'JSExpression' }},
|
||||
{ componentName: 'Leaf' },
|
||||
{ componentName: 'Slot'},
|
||||
];
|
||||
const invalidArraySchema = [
|
||||
...validArraySchema,
|
||||
{ componentName: 'ComponentWithoutProps'},
|
||||
];
|
||||
expect(isSchema(validArraySchema)).toBeTruthy();
|
||||
expect(isSchema(invalidArraySchema)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('normal valid schema should contains componentName, and props of type object or JSExpression', () => {
|
||||
expect(isSchema({ componentName: 'Button', props: {}})).toBeTruthy();
|
||||
expect(isSchema({ componentName: 'Button', props: { type: 'JSExpression' }})).toBeTruthy();
|
||||
expect(isSchema({ xxxName: 'Button'})).toBeFalsy();
|
||||
expect(isSchema({ componentName: 'Button', props: null})).toBeFalsy();
|
||||
expect(isSchema({ componentName: 'Button', props: []})).toBeFalsy();
|
||||
expect(isSchema({ componentName: 'Button', props: 'props string'})).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('test isFileSchema ', () => {
|
||||
it('should be false when invalid schema is passed', () => {
|
||||
expect(isFileSchema({ xxxName: 'Button'})).toBeFalsy();
|
||||
expect(isFileSchema({ componentName: 'Button', props: null})).toBeFalsy();
|
||||
expect(isFileSchema({ componentName: 'Button', props: []})).toBeFalsy();
|
||||
expect(isFileSchema({ componentName: 'Button', props: 'props string'})).toBeFalsy();
|
||||
});
|
||||
it('should be true only when schema with root named Page || Block || Component is passed', () => {
|
||||
expect(isFileSchema({ componentName: 'Page', props: {}})).toBeTruthy();
|
||||
expect(isFileSchema({ componentName: 'Block', props: {}})).toBeTruthy();
|
||||
expect(isFileSchema({ componentName: 'Component', props: {}})).toBeTruthy();
|
||||
expect(isFileSchema({ componentName: 'Button', props: {}})).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('test inSameDomain ', () => {
|
||||
let windowSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
windowSpy = jest.spyOn(window, "window", "get");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
windowSpy.mockRestore();
|
||||
});
|
||||
it('should work', () => {
|
||||
|
||||
windowSpy.mockImplementation(() => ({
|
||||
parent: {
|
||||
location: {
|
||||
host: "example.com"
|
||||
},
|
||||
},
|
||||
location: {
|
||||
host: "example.com"
|
||||
}
|
||||
}));
|
||||
expect(inSameDomain()).toBeTruthy();
|
||||
|
||||
windowSpy.mockImplementation(() => ({
|
||||
parent: {
|
||||
location: {
|
||||
host: "example.com"
|
||||
},
|
||||
},
|
||||
location: {
|
||||
host: "another.com"
|
||||
}
|
||||
}));
|
||||
expect(inSameDomain()).toBeFalsy();
|
||||
|
||||
windowSpy.mockImplementation(() => ({
|
||||
parent: null,
|
||||
location: {
|
||||
host: "example.com"
|
||||
}
|
||||
}));
|
||||
|
||||
expect(inSameDomain()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('test getFileCssName ', () => {
|
||||
it('should work', () => {
|
||||
expect(getFileCssName(null)).toBe(undefined);
|
||||
expect(getFileCssName(undefined)).toBe(undefined);
|
||||
expect(getFileCssName('')).toBe(undefined);
|
||||
expect(getFileCssName('FileName')).toBe('lce-file-name');
|
||||
expect(getFileCssName('Page1_abc')).toBe('lce-page1_abc');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('test isJSSlot ', () => {
|
||||
it('should work', () => {
|
||||
expect(isJSSlot(null)).toBeFalsy();
|
||||
expect(isJSSlot(undefined)).toBeFalsy();
|
||||
expect(isJSSlot('stringValue')).toBeFalsy();
|
||||
expect(isJSSlot([1, 2, 3])).toBeFalsy();
|
||||
expect(isJSSlot({ type: 'JSSlot' })).toBeTruthy();
|
||||
expect(isJSSlot({ type: 'JSBlock' })).toBeTruthy();
|
||||
expect(isJSSlot({ type: 'anyOtherType' })).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('test getValue ', () => {
|
||||
it('should check params', () => {
|
||||
expect(getValue(null, 'somePath')).toStrictEqual({});
|
||||
expect(getValue(undefined, 'somePath')).toStrictEqual({});
|
||||
// array is not valid input, return default
|
||||
expect(getValue([], 'somePath')).toStrictEqual({});
|
||||
expect(getValue([], 'somePath', 'aaa')).toStrictEqual('aaa');
|
||||
expect(getValue([1, 2, 3], 'somePath', 'aaa')).toStrictEqual('aaa');
|
||||
|
||||
expect(getValue({}, 'somePath')).toStrictEqual({});
|
||||
expect(getValue({}, 'somePath', 'default')).toStrictEqual('default');
|
||||
});
|
||||
it('should work normally', () => {
|
||||
// single segment path
|
||||
expect(getValue({ a: 'aValue' }, 'a')).toStrictEqual('aValue');
|
||||
expect(getValue({ a: 'aValue', f:null }, 'f')).toBeNull();
|
||||
expect(getValue({ a: { b: 'bValue' } }, 'a.b')).toStrictEqual('bValue');
|
||||
expect(getValue({ a: { b: 'bValue', c: { d: 'dValue' } } }, 'a.c.d')).toStrictEqual('dValue');
|
||||
expect(getValue({ a: { b: 'bValue', c: { d: 'dValue' } } }, 'e')).toStrictEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('test getI18n ', () => {
|
||||
it('should work', () => {
|
||||
const messages = {
|
||||
'zh-CN': {
|
||||
'key1': '啊啊啊',
|
||||
'key2': '哈哈哈',
|
||||
},
|
||||
};
|
||||
expect(getI18n('keyString', {}, 'zh-CN')).toStrictEqual('');
|
||||
expect(getI18n('keyString', {}, 'zh-CN', null)).toStrictEqual('');
|
||||
expect(getI18n('keyString', {}, 'en-US', messages)).toStrictEqual('');
|
||||
expect(getI18n('key3', {}, 'zh-CN', messages)).toStrictEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('test transformArrayToMap ', () => {
|
||||
it('should work', () => {
|
||||
expect(transformArrayToMap([])).toStrictEqual({});
|
||||
expect(transformArrayToMap('not a array')).toStrictEqual({});
|
||||
expect(transformArrayToMap({'not Array': 1})).toStrictEqual({});
|
||||
|
||||
let mockArray = [
|
||||
{
|
||||
name: 'jack',
|
||||
age: 2,
|
||||
},
|
||||
{
|
||||
name: 'jack',
|
||||
age: 20,
|
||||
}
|
||||
];
|
||||
// test override
|
||||
expect(transformArrayToMap(mockArray, 'name', true).jack.age).toBe(20);
|
||||
expect(transformArrayToMap(mockArray, 'name').jack.age).toBe(20);
|
||||
expect(transformArrayToMap(mockArray, 'name', false).jack.age).toBe(2);
|
||||
|
||||
mockArray = [
|
||||
{
|
||||
name: 'jack',
|
||||
age: 2,
|
||||
},
|
||||
{
|
||||
name: 'rose',
|
||||
age: 20,
|
||||
}
|
||||
];
|
||||
// normal case
|
||||
expect(transformArrayToMap(mockArray, 'name').jack.age).toBe(2);
|
||||
expect(transformArrayToMap(mockArray, 'name').jack.name).toBe('jack');
|
||||
expect(transformArrayToMap(mockArray, 'name').rose.age).toBe(20);
|
||||
// key not exists
|
||||
expect(transformArrayToMap(mockArray, 'nameEn')).toStrictEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
describe('test transformStringToFunction ', () => {
|
||||
it('should work', () => {
|
||||
const mockFun = jest.fn();
|
||||
expect(transformStringToFunction(mockFun)).toBe(mockFun);
|
||||
expect(transformStringToFunction(111)).toBe(111);
|
||||
|
||||
let mockFnStr = 'function(){return 111;}';
|
||||
let fn = transformStringToFunction(mockFnStr);
|
||||
expect(fn()).toBe(111);
|
||||
|
||||
mockFnStr = '() => { return 222; }';
|
||||
fn = transformStringToFunction(mockFnStr);
|
||||
expect(fn()).toBe(222);
|
||||
|
||||
mockFnStr = 'function getValue() { return 333; }';
|
||||
fn = transformStringToFunction(mockFnStr);
|
||||
expect(fn()).toBe(333);
|
||||
|
||||
mockFnStr = 'function getValue(aaa) {\
|
||||
return aaa; \
|
||||
}';
|
||||
fn = transformStringToFunction(mockFnStr);
|
||||
expect(fn(123)).toBe(123);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('test isVariable ', () => {
|
||||
it('should work', () => {
|
||||
expect(isVariable(null)).toBeFalsy();
|
||||
expect(isVariable(undefined)).toBeFalsy();
|
||||
expect(isVariable([1, 2, 3])).toBeFalsy();
|
||||
expect(isVariable({})).toBeFalsy();
|
||||
expect(isVariable({ type: 'any other type' })).toBeFalsy();
|
||||
expect(isVariable({ type: 'variable' })).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('test capitalizeFirstLetter ', () => {
|
||||
it('should work', () => {
|
||||
expect(capitalizeFirstLetter(null)).toBeNull();
|
||||
expect(capitalizeFirstLetter()).toBeUndefined();
|
||||
expect(capitalizeFirstLetter([1, 2, 3])).toStrictEqual([1, 2, 3]);
|
||||
expect(capitalizeFirstLetter({ a: 1 })).toStrictEqual({ a: 1 });
|
||||
expect(capitalizeFirstLetter('')).toStrictEqual('');
|
||||
expect(capitalizeFirstLetter('a')).toStrictEqual('A');
|
||||
expect(capitalizeFirstLetter('abcd')).toStrictEqual('Abcd');
|
||||
});
|
||||
});
|
||||
|
||||
describe('test forEach ', () => {
|
||||
it('should work', () => {
|
||||
const mockFn = jest.fn();
|
||||
|
||||
forEach(null, mockFn);
|
||||
expect(mockFn).toBeCalledTimes(0);
|
||||
|
||||
forEach(undefined, mockFn);
|
||||
expect(mockFn).toBeCalledTimes(0);
|
||||
|
||||
forEach([1, 2, 3], mockFn);
|
||||
expect(mockFn).toBeCalledTimes(0);
|
||||
|
||||
forEach('stringValue', mockFn);
|
||||
expect(mockFn).toBeCalledTimes(0);
|
||||
|
||||
forEach({ a: 1, b: 2, c: 3 }, mockFn);
|
||||
expect(mockFn).toBeCalledTimes(3);
|
||||
|
||||
const mockFn2 = jest.fn();
|
||||
forEach({ a: 1 }, mockFn2, { b: 'bbb' });
|
||||
expect(mockFn2).toHaveBeenCalledWith(1, 'a');
|
||||
|
||||
let sum = 0;
|
||||
const mockFn3 = function(value, key) { sum = value + this.b; };
|
||||
forEach({ a: 1 }, mockFn3, { b: 10 });
|
||||
expect(sum).toEqual(11);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test isString ', () => {
|
||||
it('should work', () => {
|
||||
expect(isString(123)).toBeFalsy();
|
||||
expect(isString([])).toBeFalsy();
|
||||
expect(isString({})).toBeFalsy();
|
||||
expect(isString(null)).toBeFalsy();
|
||||
expect(isString(undefined)).toBeFalsy();
|
||||
expect(isString(true)).toBeFalsy();
|
||||
expect(isString('111')).toBeTruthy();
|
||||
expect(isString(new String('111'))).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('test serializeParams ', () => {
|
||||
it('should work', () => {
|
||||
const mockParams = { a: 1, b: 2, c: 'cvalue', d:[1, 'a', {}], e: {e1: 'value1', e2: 'value2'}};
|
||||
const result = serializeParams(mockParams);
|
||||
const decodedParams = decodeURIComponent(result);
|
||||
expect(result).toBe('a=1&b=2&c=cvalue&d=%5B1%2C%22a%22%2C%7B%7D%5D&e=%7B%22e1%22%3A%22value1%22%2C%22e2%22%3A%22value2%22%7D');
|
||||
expect(decodedParams).toBe('a=1&b=2&c=cvalue&d=[1,"a",{}]&e={"e1":"value1","e2":"value2"}');
|
||||
});
|
||||
});
|
||||
|
||||
describe('test parseExpression ', () => {
|
||||
it('can handle JSExpression', () => {
|
||||
const mockExpression = {
|
||||
"type": "JSExpression",
|
||||
"value": "function (params) { return this.scopeValue + params.param1 + 5;}"
|
||||
};
|
||||
const result = parseExpression(mockExpression, { scopeValue: 1 });
|
||||
expect(result({ param1: 2 })).toBe((1 + 2 + 5));
|
||||
});
|
||||
});
|
||||
|
||||
describe('test parseExpression ', () => {
|
||||
it('can handle JSExpression', () => {
|
||||
const mockExpression = {
|
||||
"type": "JSExpression",
|
||||
"value": "function (params) { return this.scopeValue + params.param1 + 5;}"
|
||||
};
|
||||
const result = parseExpression(mockExpression, { scopeValue: 1 });
|
||||
expect(result({ param1: 2 })).toBe((1 + 2 + 5));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('test parseI18n ', () => {
|
||||
it('can handle normal parseI18n', () => {
|
||||
const mockI18n = {
|
||||
"type": "i18n",
|
||||
"key": "keyA"
|
||||
};
|
||||
const mockI18nFun = (key) => { return 'hahaha' + key;};
|
||||
const result = parseI18n(mockI18n, { i18n: mockI18nFun });
|
||||
expect(result).toBe('hahahakeyA');
|
||||
});
|
||||
});
|
||||
|
||||
describe('test parseData ', () => {
|
||||
it('should work when isJSExpression === true', () => {
|
||||
const mockExpression = {
|
||||
"type": "JSExpression",
|
||||
"value": "function (params) { return this.scopeValue + params.param1 + 5;}"
|
||||
};
|
||||
const result = parseData(mockExpression, { scopeValue: 1 });
|
||||
expect(result({ param1: 2 })).toBe((1 + 2 + 5));
|
||||
});
|
||||
it('should work when isI18nData === true', () => {
|
||||
const mockI18n = {
|
||||
"type": "i18n",
|
||||
"key": "keyA"
|
||||
};
|
||||
const mockI18nFun = (key) => { return 'hahaha' + key;};
|
||||
const result = parseData(mockI18n, { i18n: mockI18nFun });
|
||||
expect(result).toBe('hahahakeyA');
|
||||
});
|
||||
it('should work when schema is string', () => {
|
||||
expect(parseData(' this is a normal string, will be trimmed only ')).toStrictEqual('this is a normal string, will be trimmed only');
|
||||
});
|
||||
|
||||
it('should work when schema is array', () => {
|
||||
const mockData = [
|
||||
{
|
||||
"type": "i18n",
|
||||
"key": "keyA"
|
||||
},
|
||||
' this is a normal string, will be trimmed only ',
|
||||
];
|
||||
|
||||
const mockI18nFun = (key) => { return 'hahaha' + key;};
|
||||
const result = parseData(mockData, { i18n: mockI18nFun });
|
||||
|
||||
expect(result[0]).toStrictEqual('hahahakeyA');
|
||||
expect(result[1]).toStrictEqual('this is a normal string, will be trimmed only');
|
||||
});
|
||||
it('should work when schema is function', () => {
|
||||
const mockFn = function() { return this.a; };
|
||||
const result = parseData(mockFn, { a: 111 });
|
||||
expect(result()).toBe(111);
|
||||
});
|
||||
it('should work when schema is null or undefined', () => {
|
||||
expect(parseData(null)).toBe(null);
|
||||
expect(parseData(undefined)).toBe(undefined);
|
||||
});
|
||||
it('should work when schema is normal object', () => {
|
||||
expect(parseData({})).toStrictEqual({});
|
||||
const mockI18nFun = (key) => { return 'hahaha' + key;};
|
||||
const result = parseData({
|
||||
key1: {
|
||||
"type": "i18n",
|
||||
"key": "keyA"
|
||||
},
|
||||
key2: ' this is a normal string, will be trimmed only ',
|
||||
__privateKey: 'any value',
|
||||
}, { i18n: mockI18nFun });
|
||||
expect(result.key1).toStrictEqual('hahahakeyA');
|
||||
expect(result.key2).toStrictEqual('this is a normal string, will be trimmed only');
|
||||
expect(result.__privateKey).toBeUndefined();
|
||||
|
||||
});
|
||||
});
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-shell",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Shell Layer for AliLowCodeEngine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,11 +15,11 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.0.5",
|
||||
"@alilc/lowcode-editor-core": "1.0.5",
|
||||
"@alilc/lowcode-editor-skeleton": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-utils": "1.0.5",
|
||||
"@alilc/lowcode-designer": "1.0.6",
|
||||
"@alilc/lowcode-editor-core": "1.0.6",
|
||||
"@alilc/lowcode-editor-skeleton": "1.0.6",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"@alilc/lowcode-utils": "1.0.6",
|
||||
"classnames": "^2.2.6",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-react-16": "^1.15.5",
|
||||
|
||||
@ -84,7 +84,7 @@ export default class Node {
|
||||
/**
|
||||
* 是否为「模态框」节点
|
||||
*/
|
||||
get isModal() {
|
||||
get isModal() {
|
||||
return this[nodeSymbol].isModal();
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ export default class Node {
|
||||
/**
|
||||
* 返回节点的属性集
|
||||
*/
|
||||
get propsData() {
|
||||
get propsData() {
|
||||
return this[nodeSymbol].propsData;
|
||||
}
|
||||
|
||||
@ -226,6 +226,20 @@ export default class Node {
|
||||
return this[nodeSymbol].getDOMNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行新增、删除、排序等操作
|
||||
* @param remover
|
||||
* @param adder
|
||||
* @param sorter
|
||||
*/
|
||||
mergeChildren(
|
||||
remover: (node: Node, idx: number) => boolean,
|
||||
adder: (children: Node[]) => any,
|
||||
sorter: (firstNode: Node, secondNode: Node) => number,
|
||||
) {
|
||||
return this.children?.mergeChildren(remover, adder, sorter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回节点的尺寸、位置信息
|
||||
* @returns
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-types",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Types for Ali lowCode engine",
|
||||
"files": [
|
||||
"es",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-utils",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "Utils for Ali lowCode engine",
|
||||
"files": [
|
||||
"lib",
|
||||
@ -14,7 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-types": "1.0.5",
|
||||
"@alilc/lowcode-types": "1.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^16",
|
||||
"zen-logger": "^1.1.0"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user