mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-26 12:18:21 +00:00
chore: merge from release/1.2.3
This commit is contained in:
commit
90add387ac
51
.github/workflows/publish docs.yml
vendored
Normal file
51
.github/workflows/publish docs.yml
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
name: Update and Publish Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
paths:
|
||||
- 'docs/docs/**'
|
||||
|
||||
jobs:
|
||||
publish-docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- run: cd docs && npm install
|
||||
- run: |
|
||||
cd docs
|
||||
npm version patch
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add package.json
|
||||
git commit -m "Update package version"
|
||||
git push
|
||||
- run: cd docs && npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: echo "::set-output name=version::$(node -p "require('./docs/package.json').version")"
|
||||
|
||||
comment-pr:
|
||||
needs: publish-docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Comment on PR
|
||||
if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
|
||||
uses: actions/github-script@v4
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
github.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '🚀 New version has been released: ' + '${{ needs.publish-docs.outputs.version }}'
|
||||
})
|
||||
30
.github/workflows/publish engine beta.yml
vendored
Normal file
30
.github/workflows/publish engine beta.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
name: Publish Engine Beta
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'release/[0-9]+.[0-9]+.[0-9]+-beta'
|
||||
paths:
|
||||
- 'packages/**'
|
||||
|
||||
jobs:
|
||||
publish-engine:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- run: npm install && npm run setup
|
||||
- run: |
|
||||
npm run build
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
- run: npm run pub:prerelease
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: echo "::set-output name=version::$(node -p "require('./package.json').version")"
|
||||
@ -116,6 +116,21 @@ material.setAssets(assets1);
|
||||
material.loadIncrementalAssets(assets2);
|
||||
```
|
||||
|
||||
更新特定物料的描述文件
|
||||
|
||||
```typescript
|
||||
import { material } from '@alilc/lowcode-engine';
|
||||
material.loadIncrementalAssets({
|
||||
version: '',
|
||||
components: [
|
||||
{
|
||||
"componentName": 'Button',
|
||||
"props": [{ name: 'new', title: 'new', propType: 'string' }]
|
||||
}
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
### 设计器辅助层
|
||||
#### addBuiltinComponentAction
|
||||
在设计器辅助层增加一个扩展 action
|
||||
|
||||
@ -69,6 +69,7 @@ skeleton.add({
|
||||
props: {
|
||||
align: "left",
|
||||
icon: "wenjian",
|
||||
title: '标题', // 图标下方展示的标题
|
||||
description: "JS 面板",
|
||||
},
|
||||
panelProps: {
|
||||
@ -295,6 +296,68 @@ showArea(areaName: string): void;
|
||||
*/
|
||||
hideArea(areaName: string): void;
|
||||
```
|
||||
|
||||
### registerConfigTransducer
|
||||
注册一个面板的配置转换器(transducer)。
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* 注册一个面板的配置转换器(transducer)。
|
||||
* Registers a configuration transducer for a panel.
|
||||
* @param {IPublicTypeConfigTransducer} transducer
|
||||
* - 要注册的转换器函数。该函数接受一个配置对象(类型为 IPublicTypeSkeletonConfig)作为输入,并返回修改后的配置对象。
|
||||
* - The transducer function to be registered. This function takes a configuration object
|
||||
*
|
||||
* @param {number} level
|
||||
* - 转换器的优先级。优先级较高的转换器会先执行。
|
||||
* - The priority level of the transducer. Transducers with higher priority levels are executed first.
|
||||
*
|
||||
* @param {string} [id]
|
||||
* - (可选)转换器的唯一标识符。用于在需要时引用或操作特定的转换器。
|
||||
* - (Optional) A unique identifier for the transducer. Used for referencing or manipulating a specific transducer when needed.
|
||||
*/
|
||||
registerConfigTransducer(transducer: IPublicTypeConfigTransducer, level: number, id?: string): void;
|
||||
```
|
||||
|
||||
使用示例
|
||||
|
||||
```typescript
|
||||
import { IPublicModelPluginContext, IPublicTypeSkeletonConfig } from '@alilc/lowcode-types';
|
||||
|
||||
function updatePanelWidth(config: IPublicTypeSkeletonConfig) {
|
||||
if (config.type === 'PanelDock') {
|
||||
return {
|
||||
...config,
|
||||
panelProps: {
|
||||
...(config.panelProps || {}),
|
||||
width: 240,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
const controlPanelWidthPlugin = (ctx: IPublicModelPluginContext) => {
|
||||
const { skeleton } = ctx;
|
||||
(skeleton as any).registerConfigTransducer?.(updatePanelWidth, 1, 'update-panel-width');
|
||||
|
||||
return {
|
||||
init() {},
|
||||
};
|
||||
};
|
||||
|
||||
controlPanelWidthPlugin.pluginName = 'controlPanelWidthPlugin';
|
||||
controlPanelWidthPlugin.meta = {
|
||||
dependencies: [],
|
||||
engines: {
|
||||
lowcodeEngine: '^1.2.3', // 插件需要配合 ^1.0.0 的引擎才可运行
|
||||
},
|
||||
};
|
||||
|
||||
export default controlPanelWidthPlugin;
|
||||
```
|
||||
|
||||
## 事件
|
||||
### onShowPanel
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
- [2022/12/21 低代码多分支协同开发的建设与实践](https://mp.weixin.qq.com/s/DmwxL67htHfTUP1U966N-Q)
|
||||
- [2022/11/24 低代码引擎半岁啦,来跟大家唠唠嗑...](https://segmentfault.com/a/1190000042884409)
|
||||
- [2022/10/27 低代码技术在研发团队的应用模式探讨](https://mp.weixin.qq.com/s/Ynk_wjJbmNw7fEG6UtGZbQ)
|
||||
- [2022/08/23 基于 LowCodeEngine 的调试能力建设与实践](https://mp.weixin.qq.com/s/H8KvEOylmzLPgIuuBO0S9w)
|
||||
- [2022/06/23 低代码渲染那些事](https://mp.weixin.qq.com/s/yqYey76qLGYPfDtpGkVFfA)
|
||||
- [2022/06/16 关于 LowCode&ProCode 混合研发的思考](https://mp.weixin.qq.com/s/TY3VXjkSmsQoT47xma3wig)
|
||||
- [2022/04/07 磁贴布局在钉钉宜搭报表设计引擎中的实现](https://mp.weixin.qq.com/s/PSTut5ahAB8nlJ9kBpBaxw)
|
||||
|
||||
31
docs/docs/faq/faq023.md
Normal file
31
docs/docs/faq/faq023.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Slot组件渲染报错问题
|
||||
sidebar_position: 23
|
||||
tags: [FAQ]
|
||||
---
|
||||
|
||||
## 问题描述
|
||||
在低代码引擎的页面渲染过程中,可能会遇到一个关于Slot组件的报错,提示“Slot找不到”。实际上,在渲染态时不应使用Slot组件。
|
||||
|
||||
## 问题原因
|
||||
低代码引擎渲染分为两个状态:设计态和渲染态。
|
||||
- **设计态**:为了帮助插槽进行可视化设计,引入了Slot组件。
|
||||
- **渲染态**:在此状态下,不需要使用Slot组件。
|
||||
|
||||
这个问题通常是因为在渲染态错误地使用了设计态的schema。
|
||||
|
||||
## 解决方案
|
||||
1. **区分设计态和渲染态**:通过`project.exportSchema(TransformStage.Save)`的参数来区分。
|
||||
- `TransformStage.Save`代表渲染态的schema,其中不包含Slot组件。
|
||||
- 【默认值】`TransformStage.Render`代表设计态的schema,其中包含Slot组件。
|
||||
2. **使用正确的API和参数**:确保在渲染态使用正确的schema,避免引用设计态的Slot组件。
|
||||
3. **处理脏数据问题**:如果问题是由脏数据导致,清除数据并重新拖拽组件以恢复正常。
|
||||
|
||||
## 注意事项
|
||||
- 确保在代码和配置中正确区分设计态和渲染态。
|
||||
- 如果遇到持续的问题,检查是否有脏数据或配置错误,并进行相应的清理和调整。
|
||||
|
||||
## 相关链接
|
||||
- Issue链接:[Issue #1798](https://github.com/alibaba/lowcode-engine/issues/1798)
|
||||
|
||||
---
|
||||
133
docs/docs/faq/faq024.md
Normal file
133
docs/docs/faq/faq024.md
Normal file
@ -0,0 +1,133 @@
|
||||
---
|
||||
title: workspace 模式常见问题
|
||||
sidebar_position: 23
|
||||
tags: [FAQ]
|
||||
---
|
||||
|
||||
#### 如何判断是否开启了IDE模式?
|
||||
|
||||
- **通过官方API判断**:您可以通过访问 [workspace.isActive](/site/docs/api/workspace#isactive) 来判断当前是否处于IDE模式。这是阿里低代码引擎提供的一个官方API,专门用于确认是否处于集成开发环境。
|
||||
|
||||
|
||||
|
||||
#### 如何使用插件的ctx来做判断在哪个模式下?
|
||||
|
||||
- **插件是否为应用级别**:可以通过 **ctx.isPluginRegisteredInWorkspace** 方法来判断一个插件是否是应用级别的插件。这有助于理解插件在阿里低代码引擎中的作用域和潜在的使用场景。
|
||||
- **插件的注册级别**:您可以使用 **ctx.registerLevel** 属性来判断插件处于哪个级别。插件级别的值包括:
|
||||
- **Default**:默认级别。非 IDE 模式下的值
|
||||
- **Workspace**:应用级别。
|
||||
- **Resource**:资源级别。
|
||||
- **EditorView**:编辑视图级别。 这些级别代表了插件可能的作用域和使用场景,有助于在开发和管理低代码应用时对插件进行更精确的控制和配置。
|
||||
|
||||
|
||||
|
||||
#### 如何在IDE模式下设置资源列表?
|
||||
|
||||
- **设置资源列表API**:在IDE模式下,可以通过访问 [workspace.setResourceList](/site/docs/api/workspace#setresourcelist) 来设置或更新IDE中的资源列表。这确保您在编辑器窗口中打开的资源是最新且可访问的。
|
||||
|
||||
|
||||
|
||||
#### 如何打开视图窗口?
|
||||
|
||||
- **使用推荐的方法**:使用 `openEditorWindow(resource: Resource, sleep?: boolean): Promise<void>;` 来打开视图窗口。这里的 **resource** 参数指的是您要打开的特定资源,可通过 [workspace.resourceList](/site/docs/api/workspace#resourcelist) 获取。
|
||||
- **不推荐使用的过时方法**:有一个过时的方法 `openEditorWindow(resourceName: string, id: string, extra: Object, viewName?: string, sleep?: boolean): Promise<void>;` 也用于打开视图窗口。虽然仍然可用,但官方不推荐使用此方法,并计划在后续版本中废弃,因为它在维护和可扩展性方面存在限制。
|
||||
|
||||
|
||||
|
||||
#### 如何在全局插件中获取视图的上下文?
|
||||
|
||||
- 在阿里低代码引擎的全局插件中获取视图的上下文,可以通过使用 **ProvideViewPluginContext** 函数实现。这个函数来自 **@alilc/lowcode-utils** 库,它使得您的 React 组件能够接收 **pluginContext** 作为 props,进而访问和操作当前视图的状态和属性。
|
||||
|
||||
**步骤**
|
||||
|
||||
**引入依赖**:首先,确保您的插件文件中已经引入了 **ProvideViewPluginContext** 以及其他必要的依赖。
|
||||
|
||||
```
|
||||
import { ProvideViewPluginContext } from '@alilc/lowcode-utils';
|
||||
```
|
||||
|
||||
**定义 React 组件**:创建一个 React 组件,它将使用来自 **ProvideViewPluginContext** 的 **pluginContext**。
|
||||
|
||||
```typescript
|
||||
const MyComponent = (props) => {
|
||||
const { pluginContext } = props;
|
||||
// 组件逻辑
|
||||
return <div>/* 组件内容 */</div>;
|
||||
};
|
||||
```
|
||||
|
||||
**定义全局插件**:定义一个函数,这个函数会在插件被注册时调用。这个函数通常接受一个上下文对象 **ctx**,它提供了对引擎功能的访问。
|
||||
|
||||
```javascript
|
||||
const globalPlugin = (ctx) => {
|
||||
const { skeleton } = ctx;
|
||||
|
||||
skeleton.add({
|
||||
type: 'PanelDock',
|
||||
name: 'datapool',
|
||||
content: ProvideViewPluginContext((props) => {
|
||||
// 组件内容
|
||||
return (
|
||||
<MyComponent {...props} />
|
||||
)
|
||||
}),
|
||||
// 其他配置
|
||||
contentProps: {
|
||||
// 需要提供 pluginContext 作为参数
|
||||
pluginContext: ctx,
|
||||
}
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
通过这些步骤,您的全局插件中的 React 组件就能够获取并使用视图的上下文了。这为您在插件中实现更复杂的功能和交互提供了基础。
|
||||
|
||||
|
||||
|
||||
**注意事项**
|
||||
|
||||
- **组件重渲染**:正常情况下,**pluginsContext** 是视图的上下文。当视图切换时,组件会重新渲染。如果需要在组件中处理视图切换导致的重新渲染,可以利用 React 的 **key** 属性。
|
||||
|
||||
**示例代码**
|
||||
|
||||
```typescript
|
||||
ProvideViewPluginContext(props => {
|
||||
return (
|
||||
<DataPoolPane
|
||||
{...props}
|
||||
key={props.pluginContext?.editorWindow?.id}
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
通过这种方式,当视图切换时,组件会根据视图的不同进行重新渲染,确保组件状态与当前视图的上下文保持一致。这对于在低代码平台上开发复杂插件和交互功能是非常有用的。
|
||||
|
||||
|
||||
|
||||
#### 如何判断插件是否在 Workspace 模式下注册?
|
||||
|
||||
**使用** **ctx.isPluginRegisteredInWorkspace()** **方法**:
|
||||
|
||||
通过 **ctx.isPluginRegisteredInWorkspace()** 方法,可以判断一个插件是否在 Workspace 级别注册。以下是一个示例代码片段:
|
||||
|
||||
```javascript
|
||||
if (ctx.isPluginRegisteredInWorkspace('pluginName')) {
|
||||
console.log('插件已在 Workspace 模式下注册。');
|
||||
} else {
|
||||
console.log('插件未在 Workspace 模式下注册。');
|
||||
}
|
||||
```
|
||||
|
||||
注意:此方法目前在 beta 版本中,可能会有 TypeScript 提示显示已移除。
|
||||
|
||||
**检查** **ctx.registerLevel** **的值**:
|
||||
|
||||
可以通过比较 **ctx.registerLevel** 的值来判断插件的注册级别。示例代码如下:
|
||||
|
||||
```javascript
|
||||
if (ctx.registerLevel !== IPublicEnumPluginRegisterLevel.Workspace) {
|
||||
console.log('插件未在 Workspace 模式下注册。');
|
||||
} else {
|
||||
console.log('插件已在 Workspace 模式下注册。');
|
||||
}
|
||||
```
|
||||
@ -1,7 +1,47 @@
|
||||
---
|
||||
title: FAQ 概述
|
||||
sidebar_position: 1
|
||||
sidebar_position: -1
|
||||
tags: [FAQ]
|
||||
---
|
||||
|
||||
不定期将社区常见问题及答案维护到此处
|
||||
不定期将社区常见问题及答案维护到此处
|
||||
|
||||
## Demo 使用
|
||||
- [渲染唯一标识(key)](/site/docs/faq/faq002)
|
||||
- [点击事件如何添加参数](/site/docs/faq/faq003)
|
||||
- [如何通过 API 手动调用数据源请求](/site/docs/faq/faq006)
|
||||
|
||||
## 设计器定制
|
||||
- [如何通过 this.utils 使用第三方工具扩展](/site/docs/faq/faq005)
|
||||
- [设置面板中的高级 tab 如何配置](/site/docs/faq/faq007)
|
||||
- [插件面板如何调整位置](/site/docs/faq/faq010)
|
||||
- [workspace 模式常见问题](/site/docs/faq/faq024)
|
||||
|
||||
## 源码和依赖
|
||||
- [某某 npm 包对应的源码在哪里?](/site/docs/faq/faq008)
|
||||
|
||||
## 错误和报错
|
||||
- [物料出现 Component Not Found 相关报错](/site/docs/faq/faq009)
|
||||
- [VERSION_PLACEHOLDER is not defined](/site/docs/faq/faq014)
|
||||
- [Cannot read property 'Icon' of Undefined](/site/docs/faq/faq016)
|
||||
- [windows 下运行低代码引擎源码出现报错](/site/docs/faq/faq019)
|
||||
- [Can't import the named export from non ECMAScript module](/site/docs/faq/faq020)
|
||||
- [Slot组件渲染报错问题](/site/docs/faq/faq023)
|
||||
|
||||
## 物料相关问题
|
||||
- [如何获取物料当前处于编辑态还是渲染态](/site/docs/faq/faq011)
|
||||
- [Procode 物料如何调用数据源方法](/site/docs/faq/faq012)
|
||||
- [已有组件如何快速接入引擎](/site/docs/faq/faq015)
|
||||
- [Modal 类组件 hidden 属性被强制设置 true](/site/docs/faq/faq013)
|
||||
- [最小渲染单元配置](/site/docs/faq/faq004)
|
||||
- [节点无法拖拽到 Page 下](/site/docs/faq/faq022)
|
||||
|
||||
## 其他说明
|
||||
- [vue 画布支持说明](/site/docs/faq/faq017)
|
||||
- [是否可以生成 Vue 页面代码?](/site/docs/faq/faq018)
|
||||
|
||||
## 参与贡献
|
||||
- [提交 PR 时,明明签署过 CLA,仍被提示需要签署](/site/docs/faq/faq021)
|
||||
|
||||
## 相关依赖文档
|
||||
- [build-scripts 的使用文档](/site/docs/faq/faq001)
|
||||
|
||||
@ -3,23 +3,47 @@ title: 主题色扩展
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
## 主题色扩展简述
|
||||
## 简介
|
||||
|
||||
通过主题色扩展,可以定制多种设计器主题。
|
||||
主题色扩展允许用户定制多样的设计器主题,增加界面的个性化和品牌识别度。
|
||||
|
||||
## 主题色扩展说明
|
||||
## 设计器主题色定制
|
||||
|
||||
在 CSS 的根级别定义主题色变量可以确保这些变量在整个应用中都可用。例如:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-brand: rgba(0, 108, 255, 1); /* 主品牌色 */
|
||||
--color-brand-light: rgba(25, 122, 255, 1); /* 浅色品牌色 */
|
||||
--color-brand-dark: rgba(0, 96, 229, 1); /* 深色品牌色 */
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
将样式文件引入到你的设计器中,定义的 CSS 变量就可以改变设计器的主题色了。
|
||||
|
||||
### 主题色变量
|
||||
|
||||
- `--color-brand`: 品牌色
|
||||
- `--color-brand-light`: 品牌色(light)
|
||||
- `--color-brand-dark`: 品牌色(dark)
|
||||
- `--color-icon-normal`: 正常 icon 颜色
|
||||
- `--color-icon-hover`: icon hover 态颜色
|
||||
- `--color-icon-active`: icon active 态颜色
|
||||
- `--color-icon-reverse`: icon 反色
|
||||
- `--color-icon-disabled`: icon 禁用态颜色
|
||||
- `--color-icon-pane`: icon 面板颜色
|
||||
以下是低代码引擎设计器支持的主题色变量列表,以及它们的用途说明:
|
||||
|
||||
#### 品牌相关颜色
|
||||
|
||||
- `--color-brand`: 主品牌色
|
||||
- `--color-brand-light`: 浅色品牌色
|
||||
- `--color-brand-dark`: 深色品牌色
|
||||
|
||||
#### Icon 相关颜色
|
||||
|
||||
- `--color-icon-normal`: 默认状态
|
||||
- `--color-icon-light`: icon light 状态
|
||||
- `--color-icon-hover`: 鼠标悬停状态
|
||||
- `--color-icon-active`: 激活状态
|
||||
- `--color-icon-reverse`: 反色状态
|
||||
- `--color-icon-disabled`: 禁用状态
|
||||
- `--color-icon-pane`: 面板颜色
|
||||
|
||||
#### 线条和文本颜色
|
||||
|
||||
- `--color-line-normal`: 线条颜色
|
||||
- `--color-line-darken`: 线条颜色(darken)
|
||||
- `--color-title`: 标题颜色
|
||||
@ -27,8 +51,10 @@ sidebar_position: 9
|
||||
- `--color-text-dark`: 文字颜色(dark)
|
||||
- `--color-text-light`: 文字颜色(light)
|
||||
- `--color-text-reverse`: 反色情况下,文字颜色
|
||||
- `--color-text-regular`: 文字颜色(regular)
|
||||
- `--color-text-disabled`: 禁用态文字颜色
|
||||
|
||||
#### 字段和边框颜色
|
||||
|
||||
- `--color-field-label`: field 标签颜色
|
||||
- `--color-field-text`: field 文本颜色
|
||||
- `--color-field-placeholder`: field placeholder 颜色
|
||||
@ -36,6 +62,9 @@ sidebar_position: 9
|
||||
- `--color-field-border-hover`: hover 态下,field 边框颜色
|
||||
- `--color-field-border-active`: active 态下,field 边框颜色
|
||||
- `--color-field-background`: field 背景色
|
||||
|
||||
#### 状态颜色
|
||||
|
||||
- `--color-success`: success 颜色
|
||||
- `--colo-success-dark`: success 颜色(dark)
|
||||
- `--color-success-light`: success 颜色(light)
|
||||
@ -50,30 +79,59 @@ sidebar_position: 9
|
||||
- `--color-error-light`: error 颜色(light)
|
||||
- `--color-purple`: purple 颜色
|
||||
- `--color-brown`: brown 颜色
|
||||
- `--color-pane-background`: 面板背景色
|
||||
|
||||
#### 区块背景色
|
||||
|
||||
- `--color-block-background-normal`: 区块背景色
|
||||
- `--color-block-background-light`: 区块背景色(light), 作用于画布组件 hover 时遮罩背景色。
|
||||
- `--color-block-background-light`: 区块背景色(light)。
|
||||
- `--color-block-background-shallow`: 区块背景色 shallow
|
||||
- `--color-block-background-dark`: 区块背景色(dark)
|
||||
- `--color-block-background-disabled`: 区块背景色(disabled)
|
||||
- `--color-block-background-active`: 区块背景色(active)
|
||||
- `--color-block-background-active-light`: 区块背景色(active light)
|
||||
- `--color-block-background-warning`: 区块背景色(warning)
|
||||
- `--color-block-background-error`: 区块背景色(error)
|
||||
- `--color-block-background-success`: 区块背景色(success)
|
||||
- `--color-block-background-deep-dark`: 区块背景色(deep-dark),作用于多个组件同时拖拽的背景色。
|
||||
|
||||
#### 引擎相关颜色
|
||||
|
||||
- `--color-canvas-detecting-background`: 画布组件 hover 时遮罩背景色。
|
||||
|
||||
#### 其他区域背景色
|
||||
|
||||
- `--color-layer-mask-background`: 拖拽元素时,元素原来位置的遮罩背景色
|
||||
- `--color-layer-tooltip-background`: tooltip 背景色
|
||||
- `--color-pane-background`: 面板背景色
|
||||
- `--color-background`: 设计器主要背景色
|
||||
- `--color-top-area-background`: topArea 背景色,优先级大于 `--color-pane-background`
|
||||
- `--color-left-area-background`: leftArea 背景色,优先级大于 `--color-pane-background`
|
||||
- `--color-toolbar-background`: toolbar 背景色,优先级大于 `--color-pane-background`
|
||||
- `--color-workspace-left-area-background`: 应用级 leftArea 背景色,优先级大于 `--color-pane-background`
|
||||
- `--color-workspace-top-area-background`: 应用级 topArea 背景色,优先级大于 `--color-pane-background`
|
||||
- `--color-workspace-sub-top-area-background`: 应用级二级 topArea 背景色,优先级大于 `--color-pane-background`
|
||||
|
||||
#### 其他变量
|
||||
|
||||
- `--workspace-sub-top-area-height`: 应用级二级 topArea 高度
|
||||
- `--top-area-height`: 顶部区域的高度
|
||||
- `--workspace-sub-top-area-margin`: 应用级二级 topArea margin
|
||||
- `--workspace-sub-top-area-padding`: 应用级二级 topArea padding
|
||||
- `--workspace-left-area-width`: 应用级 leftArea width
|
||||
- `--left-area-width`: leftArea width
|
||||
- `--simulator-top-distance`: simulator 距离容器顶部的距离
|
||||
- `--simulator-bottom-distance`: simulator 距离容器底部的距离
|
||||
- `--simulator-left-distance`: simulator 距离容器左边的距离
|
||||
- `--simulator-right-distance`: simulator 距离容器右边的距离
|
||||
- `--toolbar-padding`: toolbar 的 padding
|
||||
- `--toolbar-height`: toolbar 的高度
|
||||
- `--pane-title-height`: 面板标题高度
|
||||
- `--pane-title-font-size`: 面板标题字体大小
|
||||
- `--pane-title-padding`: 面板标题边距
|
||||
|
||||
### 生态使用主题色变量
|
||||
|
||||
|
||||
### 低代码引擎生态主题色定制
|
||||
|
||||
插件、物料、设置器等生态为了支持主题色需要对样式进行改造,需要对生态中的样式升级为 css 变量。例如:
|
||||
|
||||
@ -86,6 +144,8 @@ background: var(--color-brand, #006cff);
|
||||
|
||||
```
|
||||
|
||||
这里 `var(--color-brand, #默认色)` 表示使用 `--color-brand` 变量,如果该变量未定义,则使用默认颜色(#默认色)。
|
||||
|
||||
### fusion 物料进行主题色扩展
|
||||
|
||||
如果使用了 fusion 组件,可以通过 https://fusion.alibaba-inc.com/ 平台进行主题色定制。
|
||||
如果使用了 fusion 组件时,可以通过 [fusion 平台](https://fusion.design/) 进行主题色定制。在平台上,您可以选择不同的主题颜色,并直接应用于您的 fusion 组件,这样可以无缝地集成到您的应用设计中。
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: 试用低代码引擎 Demo
|
||||
sidebar_position: 1
|
||||
sidebar_position: 2
|
||||
---
|
||||
## 访问地址
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: 简介
|
||||
sidebar_position: 0
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# 阿里低代码引擎简介
|
||||
@ -46,3 +46,18 @@ sidebar_position: 0
|
||||
**低代码设计器研发框架**
|
||||
|
||||
低代码引擎的核心是设计器,通过扩展、周边生态等可以产出各式各样的设计器。它不是一套可以适合所有人的低代码平台,而是帮助低代码平台的开发者,快速生产低代码平台的工具。
|
||||
|
||||
## 寻找适合您的低代码解决方案
|
||||
|
||||
帮助用户根据个人或企业需求选择合适的低代码产品。
|
||||
|
||||
| 特性/产品 | 低代码引擎 | Lab平台 | UIPaaS |
|
||||
|-----------------|-----------------------------------------|-----------------------------------------|--------------------------------------------|
|
||||
| **适用用户** | 前端开发者 | 需要快速搭建应用/页面的用户 | 企业用户,需要大规模部署低代码解决方案的组织 |
|
||||
| **产品特点** | 设计器研发框架,适合定制开发 | 低代码平台, 可视化操作界面,易于上手 | 低代码平台孵化器,企业级功能 |
|
||||
| **使用场景** | 定制和开发低代码平台的设计器部分 | 通过可视化, 快速开发应用或页面 | 帮助具有一定规模软件研发团队的的企业低成本定制低代码平台 |
|
||||
| **产品关系** | 开源产品 | 基于UIPaaS技术实现, 展示了UIPaaS的部分能力 | 提供完整的低代码平台解决方案,商业产品 |
|
||||
| **收费情况** | 免费 | 可免费使用(有额度限制),不提供私有化部署售卖 | 仅提供私有化部署售卖 |
|
||||
| **官方网站** | [低代码引擎官网](https://lowcode-engine.cn/) | [Lab平台官网](https://lab.lowcode-engine.cn/) | [UIPaaS官网](https://uipaas.net/) |
|
||||
|
||||
*注:请根据您的具体需求和条件选择合适的产品。如需更详细的信息,请访问各产品的官方网站。*
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
sidebar_position: 3
|
||||
title: 快速开始
|
||||
---
|
||||
|
||||
|
||||
@ -1,88 +0,0 @@
|
||||
---
|
||||
title: 工程化配置
|
||||
sidebar_position: 3
|
||||
---
|
||||
目前引擎体系共包含 2 个 js 文件 (配套 2 个 css),即:
|
||||
|
||||
|
||||
```html
|
||||
<!-- 低代码引擎的页面框架样式 -->
|
||||
<link rel="stylesheet" href="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.18/dist/css/engine-core.css" />
|
||||
<!-- 低代码引擎官方扩展的样式 -->
|
||||
<link rel="stylesheet" href="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/css/engine-ext.css" />
|
||||
|
||||
<!-- 低代码引擎的主包 -->
|
||||
<script crossorigin="anonymous" src="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.18/dist/js/engine-core.js"></script>
|
||||
<!-- 低代码引擎官方扩展的主包 -->
|
||||
<script crossorigin="anonymous" src="https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/js/engine-ext.js"></script>
|
||||
```
|
||||
|
||||
> 注,这里的版本号是示例,请尽量选用最新版
|
||||
|
||||
工程化配置我们进行了统一,具体如下:
|
||||
```shell
|
||||
{
|
||||
"entry": {
|
||||
...
|
||||
},
|
||||
"library": "...",
|
||||
"libraryTarget": "umd",
|
||||
"externals": {
|
||||
"react": "var window.React",
|
||||
"react-dom": "var window.ReactDOM",
|
||||
"prop-types": "var window.PropTypes",
|
||||
"@alilc/lowcode-engine": "var window.AliLowCodeEngine",
|
||||
"@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt",
|
||||
"moment": "var moment",
|
||||
"lodash": "var _",
|
||||
"@alifd/next": "var Next"
|
||||
},
|
||||
"polyfill": false,
|
||||
"outputDir": "dist",
|
||||
"vendor": false,
|
||||
"ignoreHtmlTemplate": true,
|
||||
"sourceMap": true,
|
||||
"plugins": [
|
||||
"build-plugin-react-app",
|
||||
["build-plugin-fusion", {
|
||||
}],
|
||||
["build-plugin-moment-locales", {
|
||||
"locales": ["zh-CN"]
|
||||
}],
|
||||
"./build.plugin.js"
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
总结一下,有 2 点:
|
||||
|
||||
1. **都不包含 polyfill,**需要应用级别单独引入 polyfill,推荐动态 polyfill
|
||||
2. **都不包含 lodash / moment / next**
|
||||
|
||||
|
||||
#### 前置依赖资源:
|
||||
```html
|
||||
<link rel="stylesheet" href="//alifd.alicdn.com/npm/@alifd/next/1.20.25/next.min.css">
|
||||
|
||||
<script src="//polyfill.alicdn.com/s/polyfill.min.js?features=default,es2017,es6,fetch,RegeneratorRuntime"></script>
|
||||
<script src="//alifd.alicdn.com/npm/@alifd/next/1.20.25/next.min.js"></script>
|
||||
<script src="//g.alicdn.com/platform/c/lodash/4.6.1/lodash.min.js"></script>
|
||||
<script src="//g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
|
||||
```
|
||||
|
||||
|
||||
#### 所有资源:
|
||||
```html
|
||||
<link rel="stylesheet" href="//alifd.alicdn.com/npm/@alifd/next/1.20.25/next.min.css">
|
||||
<link rel="stylesheet" href="//uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.18/dist/css/engine-core.css"/>
|
||||
<link rel="stylesheet" href="//uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.5/dist/css/engine-ext.css"/>
|
||||
|
||||
<script src="//polyfill.alicdn.com/s/polyfill.min.js?features=default,es2017,es6,fetch,RegeneratorRuntime"></script>
|
||||
<script src="//alifd.alicdn.com/npm/@alifd/next/1.20.25/next.min.js"></script>
|
||||
<script src="//g.alicdn.com/platform/c/lodash/4.6.1/lodash.min.js"></script>
|
||||
<script src="//g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
|
||||
<!-- engine-core 引擎的 core,负责引擎的基础模块 -->
|
||||
<script crossorigin="anonymous" src="//uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.18/dist/js/engine-core.js"></script>
|
||||
<!-- engine-ext 引擎的扩展包,负责收拢内置 setters / plugins,方便迭代 -->
|
||||
<script crossorigin="anonymous" src="//uipaas-assets.com/prod/npm/@alilc/lowcode-engine/1.0.5/dist/js/engine-ext.js"></script>
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
title: 参与文档贡献
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
## 基本原则
|
||||
|
||||
### 维护方式
|
||||
|
||||
- 官方文档通过 github 管理文档源,官网文档与[主仓库 develop 分支](https://github.com/alibaba/lowcode-engine/tree/develop/docs)保持同步。
|
||||
- 点击每篇文档下发的 `编辑此页` 可直接定位到 github 中位置。
|
||||
- 欢迎 PR,文档 PR 也会作为贡献者贡献,会用于贡献度统计。
|
||||
- **文档同步到官方网站由官方人员进行操作**,如有需要可以通过 issue 或 贡献者群与相关人员沟通。
|
||||
- 为了提供更好的阅读和使用体验,文档中的图片文件会定期转换成可信的 CDN 地址。
|
||||
|
||||
### PR 提交注意事项
|
||||
|
||||
- 指向 develop 分支。
|
||||
- 涉及到图片的,需附在文档同级的 img 目录下,通过相对地址引用。
|
||||
|
||||
### 文档格式
|
||||
|
||||
本项目文档参考[文档编写指南](https://github.com/sparanoid/chinese-copywriting-guidelines)。
|
||||
|
||||
使用 vscode 进行编辑的朋友可以安装 vscode 插件 [huacnlee.autocorrect](https://github.com/huacnlee/autocorrect) 辅助文档 lint。
|
||||
@ -1,31 +1,126 @@
|
||||
---
|
||||
title: 贡献者指南
|
||||
title: 参与贡献
|
||||
sidebar_position: 0
|
||||
---
|
||||
### 首个 Pull Request
|
||||
在写第一个 Pull Request?你可以从这一系列视频中学习怎么做:
|
||||
[How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github)
|
||||
|
||||
### 环境准备
|
||||
|
||||
开发 LowcodeEngine 需要 Node.js 16+。
|
||||
|
||||
推荐使用 nvm 管理 Node.js,避免权限问题的同时,还能够随时切换当前使用的 Node.js 的版本。
|
||||
|
||||
### 贡献低代码引擎
|
||||
|
||||
#### clone 项目
|
||||
|
||||
```
|
||||
git clone git@github.com:alibaba/lowcode-engine.git
|
||||
cd lowcode-engine
|
||||
```
|
||||
|
||||
#### 安装依赖并构建
|
||||
|
||||
```
|
||||
npm install && npm run setup
|
||||
```
|
||||
|
||||
#### 调试环境配置
|
||||
|
||||
本质上是将 demo 页面引入的几个 js/css 代理到 engine 项目,可以使用趁手的代理工具,这里推荐 [XSwitch](https://chrome.google.com/webstore/detail/xswitch/idkjhjggpffolpidfkikidcokdkdaogg?hl=en-US)。
|
||||
|
||||
本地开发代理规则如下:
|
||||
```json
|
||||
{
|
||||
"proxy": [
|
||||
[
|
||||
"https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/engine-core.js",
|
||||
"http://localhost:5555/js/AliLowCodeEngine.js"
|
||||
],
|
||||
[
|
||||
"https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/engine-core.css",
|
||||
"http://localhost:5555/css/AliLowCodeEngine.css"
|
||||
],
|
||||
[
|
||||
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/react-simulator-renderer.js",
|
||||
"http://localhost:5555/js/ReactSimulatorRenderer.js"
|
||||
],
|
||||
[
|
||||
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/react-simulator-renderer.css",
|
||||
"http://localhost:5555/css/ReactSimulatorRenderer.css"
|
||||
],
|
||||
[
|
||||
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/rax-simulator-renderer.js",
|
||||
"http://localhost:5555/js/RaxSimulatorRenderer.js"
|
||||
],
|
||||
[
|
||||
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/rax-simulator-renderer.css",
|
||||
"http://localhost:5555/css/RaxSimulatorRenderer.css"
|
||||
],
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 开发
|
||||
|
||||
```
|
||||
npm start
|
||||
```
|
||||
|
||||
选择一个环境进行调试,例如[低代码引擎在线 DEMO](https://lowcode-engine.cn/demo/demo-general/index.html)
|
||||
|
||||
开启代理之后,就可以进行开发调试了。
|
||||
|
||||
|
||||
### 贡献低代码引擎文档
|
||||
|
||||
#### 开发文档
|
||||
|
||||
在 lowcode-engine 目录下执行下面命令
|
||||
```
|
||||
cd docs
|
||||
|
||||
npm start
|
||||
```
|
||||
|
||||
#### 维护方式
|
||||
- 官方文档通过 github 管理文档源,官网文档与[主仓库 develop 分支](https://github.com/alibaba/lowcode-engine/tree/develop/docs)保持同步。
|
||||
- 点击每篇文档下发的 `编辑此页` 可直接定位到 github 中位置。
|
||||
- 欢迎 PR,文档 PR 也会作为贡献者贡献,会用于贡献度统计。
|
||||
- **文档同步到官方网站由官方人员进行操作**,如有需要可以通过 issue 或 贡献者群与相关人员沟通。
|
||||
- 为了提供更好的阅读和使用体验,文档中的图片文件会定期转换成可信的 CDN 地址。
|
||||
|
||||
#### 文档格式
|
||||
|
||||
本项目文档参考[文档编写指南](https://github.com/sparanoid/chinese-copywriting-guidelines)。
|
||||
|
||||
使用 vscode 进行编辑的朋友可以安装 vscode 插件 [huacnlee.autocorrect](https://github.com/huacnlee/autocorrect) 辅助文档 lint。
|
||||
|
||||
|
||||
### 贡献低代码引擎生态
|
||||
|
||||
相关源码详见[NPM 包对应源码位置汇总](/site/docs/guide/appendix/npms)
|
||||
|
||||
开发调试方式详见[低代码生态脚手架 & 调试机制](/site/docs/guide/expand/editor/cli)
|
||||
|
||||
### 发布
|
||||
|
||||
PR 被合并之后,我们会尽快发布相关的正式版本或者 beta 版本。
|
||||
|
||||
### 加入 Contributor 群
|
||||
提交过 Bugfix 或 Feature 类 PR 的同学,如果有兴趣一起参与维护 LowcodeEngine,我们提供了一个核心贡献者交流群。
|
||||
|
||||
1. 可以通过[填写问卷](https://survey.taobao.com/apps/zhiliao/4YEtu9gHF)的方式,参与到其中。
|
||||
2. 填写问卷后加微信号 `wxidvlalalalal` (注明 github id)我们会拉你到群里。
|
||||
|
||||
如果你不知道可以贡献什么,可以到源码里搜 TODO 或 FIXME 找找。
|
||||
|
||||
为了使你能够快速上手和熟悉贡献流程,我们这里有个列表 [good first issues](https://github.com/alibaba/lowcode-engine/issues?q=is:open+is:issue+label:%22good+first+issue%22),里面有相对没那么笼统的漏洞,从这开始是个不错的选择。
|
||||
|
||||
如果你想解决一个 issue,请确定检查了该 issue 下的评论以防有人正在处理它。如果目前没人在处理该 issue,那么请留下评论去表明你想处理该 issue 以便其他人不会意外重复你的工作。
|
||||
### PR 提交注意事项
|
||||
|
||||
如果有人留言表明要处理该 issue 但是超过两周没有跟进,你可以接手工作,不过也应该留言说明。
|
||||
|
||||
### 提交 Pull Request
|
||||
核心团队时刻关注 pull requests,我们会先评审你的 pull request,之后可能会合并,可能会要求再次更改,也可能会关闭该 pull request 并对此作出解释。我们会尽力全程更新和反馈。
|
||||
|
||||
**提交 pull request 前**,请确保完成以下步骤:
|
||||
|
||||
1. Fork [此仓库](https://github.com/alibaba/lowcode-engine),从 main 创建分支。
|
||||
2. 在仓库根目录下执行 yarn。
|
||||
3. 如果你修复了 bug 或者添加了代码,而这些内容需要测试,请添加测试!
|
||||
4. 确保通过测试套件(yarn test)。
|
||||
5. 请签订贡献者许可证协议(Contributor License Agreement)。
|
||||
> 如已签署 CLA 仍被提示需要签署,[解决办法](/site/docs/faq/faq021)
|
||||
|
||||
### 核心贡献者交流
|
||||
如果你想长期参与到项目维护中,我们提供了一个核心贡献者交流群。
|
||||
|
||||
1. 可以通过[填写问卷](https://survey.taobao.com/apps/zhiliao/4YEtu9gHF)的方式,参与到其中。
|
||||
2. 填写问卷后加微信号 `wxidvlalalalal` 说明一下。
|
||||
- lowcode-engine 仓库建议从 develop 创建分支,PR 指向 develop 分支。
|
||||
- 其他仓库从 main 分支创建分支,PR 指向 main 分支
|
||||
- 如果你修复了 bug 或者添加了代码,而这些内容需要测试,请添加测试!
|
||||
- 确保通过测试套件(yarn test)。
|
||||
- 请签订贡献者许可证协议(Contributor License Agreement)。
|
||||
> 如已签署 CLA 仍被提示需要签署,[解决办法](/site/docs/faq/faq021)
|
||||
55
docs/docs/participate/meet.md
Normal file
55
docs/docs/participate/meet.md
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
title: 开源社区例会
|
||||
sidebar_position: 0
|
||||
---
|
||||
|
||||
## **简介**
|
||||
|
||||
低代码引擎开源社区致力于共同推动低代码技术的发展和创新。本社区汇集了低代码技术领域的开发者、技术专家和行业观察者,通过定期的例会来交流思想、分享经验、讨论新技术,并探索低代码技术的未来发展方向。
|
||||
|
||||
## 参与要求
|
||||
|
||||
为了确保例会的质量和效果,我们建议以下人员参加:
|
||||
|
||||
- **已参与低代码引擎贡献的成员**:那些对低代码引擎有实际贡献的社区成员。
|
||||
- **参考贡献指南**:可查阅[贡献指南](https://lowcode-engine.cn/site/docs/participate/)获取更多信息。
|
||||
- **提供过优秀建议的成员**:那些在过去为低代码引擎提供过有价值建议的成员。
|
||||
|
||||
## **时间周期**
|
||||
|
||||
- **周期性**:月例会
|
||||
|
||||
### **特别说明**
|
||||
|
||||
- 例会周期可根据成员反馈进行调整。如果讨论的议题较多,可增加例会频率;若议题较少,单次例会可能取消。若多次取消,可能会暂停例会。
|
||||
|
||||
## **例会流程**
|
||||
|
||||
### **准备阶段**
|
||||
|
||||
- **定期确定议题**:会前一周确定下一次会议的议题。
|
||||
- **分发会议通知**:提前发送会议时间、议程和参与方式。
|
||||
|
||||
### **会议阶段**
|
||||
|
||||
- **开场和介绍**:简短开场和自我介绍,特别是新成员加入时。
|
||||
- **议题讨论**:按照议程进行议题讨论,每个议题分配一定时间,并留足够时间供讨论和提问。
|
||||
- **记录要点和决定**:记录讨论要点、决策和任何行动事项。
|
||||
|
||||
### **后续阶段**
|
||||
|
||||
- **分享会议纪要**:会后将会议纪要和行动计划分发给所有成员。
|
||||
- **执行和跟进**:根据会议中的讨论和决策执行相关任务,并在下次会议中进行跟进汇报。
|
||||
|
||||
## **开源例会议题**
|
||||
|
||||
开源例会议题包括但不限于:
|
||||
|
||||
- **共建低代码行业发展**:探讨通过开源社区合作加速低代码行业发展。
|
||||
- **改进建议和反馈收集**:讨论社区成员对低代码引擎的使用体验和改进建议。
|
||||
- **前端技术与低代码的结合**:针对前端开发者,讨论将前端技术与低代码引擎结合的方式。
|
||||
- **低代码业务场景和经验分享**:邀请社区成员分享低代码引擎的实际应用经验。
|
||||
- **低代码技术原理介绍**:深入理解低代码引擎的技术原理和实现方式。
|
||||
- **低代码引擎的最新进展**:分享低代码引擎的最新进展,包括新版本发布和新功能实现等。
|
||||
- **低代码技术的未来展望**:讨论低代码技术的未来发展方向。
|
||||
- **最新低代码平台功能和趋势分析**:分享和讨论当前低代码平台的新功能、趋势和发展方向。
|
||||
@ -1,64 +0,0 @@
|
||||
---
|
||||
title: 调试环境配置
|
||||
sidebar_position: 1
|
||||
---
|
||||
低代码引擎的核心仓库是不包含任何物料、插件、setter 的,它本身用于生成低代码引擎的主包。
|
||||
|
||||
如果您需要对低代码的主包进行开发和调试,需要用到本文里介绍的知识。
|
||||
|
||||
如果您需要对低代码编辑器进行定制,您可能只需要 clone [lowcode-demo 项目](https://github.com/alibaba/lowcode-demo)并进行修改,参考“[配置低代码扩展点](/site/docs/guide/expand/editor/summary)”章节。
|
||||
|
||||
> 前置条件:
|
||||
> node 推荐使用 16.18.0(14.x 也可以)
|
||||
|
||||
### 1. 拉取代码,启动项目
|
||||
```bash
|
||||
git clone git@github.com:alibaba/lowcode-engine.git
|
||||
cd lowcode-engine
|
||||
npm install && npm run setup
|
||||
npm start
|
||||
|
||||
|
||||
git clone git@github.com:alibaba/lowcode-demo.git
|
||||
cd lowcode-demo
|
||||
npm install && npm start
|
||||
```
|
||||
|
||||
### 2. 配置资源代理
|
||||
本质上是将 demo 页面引入的几个 js/css 代理到 engine 项目,可以使用趁手的代理工具,这里推荐 [XSwitch](https://chrome.google.com/webstore/detail/xswitch/idkjhjggpffolpidfkikidcokdkdaogg?hl=en-US)。
|
||||
|
||||
本地开发代理规则如下:
|
||||
```json
|
||||
{
|
||||
"proxy": [
|
||||
[
|
||||
"https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/engine-core.js",
|
||||
"http://localhost:5555/js/engine-core.js"
|
||||
],
|
||||
[
|
||||
"https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/engine-core.css",
|
||||
"http://localhost:5555/css/engine-core.css"
|
||||
],
|
||||
[
|
||||
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/react-simulator-renderer.js",
|
||||
"http://localhost:5555/js/react-simulator-renderer.js"
|
||||
],
|
||||
[
|
||||
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/react-simulator-renderer.css",
|
||||
"http://localhost:5555/css/react-simulator-renderer.css"
|
||||
],
|
||||
[
|
||||
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/js/rax-simulator-renderer.js",
|
||||
"http://localhost:5555/js/rax-simulator-renderer.js"
|
||||
],
|
||||
[
|
||||
"https?://uipaas-assets.com/prod/npm/@alilc/lowcode-engine/(.*)/dist/css/rax-simulator-renderer.css",
|
||||
"http://localhost:5555/css/rax-simulator-renderer.css"
|
||||
],
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 本地调试物料/插件/设置器
|
||||
|
||||
详见[低代码生态脚手架 & 调试机制](/site/docs/guide/expand/editor/cli)
|
||||
@ -1,4 +1,5 @@
|
||||
# 官方视频
|
||||
- [2023/11/20 云栖大会|阿里开源低代码引擎及商业解决方案](https://www.bilibili.com/video/BV1Ku4y1w7Zr)
|
||||
- [2023/08/03 初识低代码引擎](https://www.bilibili.com/video/BV1gu411p7TC)
|
||||
|
||||
# 社区视频
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-engine-docs",
|
||||
"version": "1.1.14",
|
||||
"version": "1.2.10",
|
||||
"description": "低代码引擎版本化文档",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"lerna": "4.0.0",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"packages": [
|
||||
|
||||
@ -20,11 +20,11 @@
|
||||
"lint:fix": "f2elint fix -i ./packages/*/src",
|
||||
"lint:modules": "f2elint scan -q -i ./modules/*/src",
|
||||
"lint:modules:fix": "f2elint fix -i ./modules/*/src",
|
||||
"pub": "npm run watchdog:build && lerna publish patch --force-publish --exact --no-changelog",
|
||||
"pub": "npm run watchdog:build && lerna publish patch --yes --force-publish --exact --no-changelog",
|
||||
"pub:premajor": "npm run watchdog:build && lerna publish premajor --force-publish --exact --dist-tag beta --preid beta --no-changelog",
|
||||
"pub:preminor": "npm run watchdog:build && lerna publish preminor --force-publish --exact --dist-tag beta --preid beta --no-changelog",
|
||||
"pub:prepatch": "npm run watchdog:build && lerna publish prepatch --force-publish --exact --dist-tag beta --preid beta --no-changelog",
|
||||
"pub:prerelease": "npm run watchdog:build && lerna publish prerelease --force-publish --exact --dist-tag beta --preid beta --no-changelog",
|
||||
"pub:prerelease": "npm run watchdog:build && lerna publish prerelease --yes --force-publish --exact --dist-tag beta --preid beta --no-changelog",
|
||||
"setup": "node ./scripts/setup.js",
|
||||
"setup:test": "./scripts/setup-for-test.sh",
|
||||
"setup:skip-build": "./scripts/setup-skip-build.sh",
|
||||
|
||||
@ -20,6 +20,7 @@ const jestConfig = {
|
||||
// testMatch: ['**/node.test.ts'],
|
||||
// testMatch: ['**/builtin-hotkey.test.ts'],
|
||||
// testMatch: ['**/selection.test.ts'],
|
||||
// testMatch: ['**/plugin/sequencify.test.ts'],
|
||||
transformIgnorePatterns: [
|
||||
`/node_modules/(?!${esModules})/`,
|
||||
],
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-designer",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "Designer for Ali LowCode Engine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -15,9 +15,9 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-editor-core": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-editor-core": "1.2.3",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16",
|
||||
"react-dom": "^16.7.0",
|
||||
|
||||
@ -143,7 +143,7 @@ function createAction(content: ReactNode | ComponentType<any> | IPublicTypeActio
|
||||
});
|
||||
}}
|
||||
>
|
||||
{icon && createIcon(icon)}
|
||||
{icon && createIcon(icon, { key, node: node.internalToShellNode() })}
|
||||
<Tip>{title}</Tip>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -100,7 +100,7 @@
|
||||
&&-detecting {
|
||||
z-index: 1;
|
||||
border-style: dashed;
|
||||
background: var(--color-block-background-light, rgba(0,121,242,.04));
|
||||
background: var(--color-canvas-detecting-background, rgba(0,121,242,.04));
|
||||
}
|
||||
|
||||
&&-selecting {
|
||||
|
||||
@ -73,10 +73,10 @@
|
||||
}
|
||||
|
||||
&-device-default {
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
left: 16px;
|
||||
top: var(--simulator-top-distance, 16px);
|
||||
right: var(--simulator-right-distance, 16px);
|
||||
bottom: var(--simulator-bottom-distance, 16px);
|
||||
left: var(--simulator-left-distance, 16px);
|
||||
width: auto;
|
||||
box-shadow: 0 1px 4px 0 var(--color-block-background-shallow, rgba(31, 50, 88, 0.125));
|
||||
}
|
||||
|
||||
@ -2,3 +2,4 @@ export * from './host';
|
||||
export * from './host-view';
|
||||
export * from './renderer';
|
||||
export * from './live-editing/live-editing';
|
||||
export { LowcodeTypes } from './utils/parse-metadata';
|
||||
|
||||
@ -46,13 +46,15 @@ function define(propType: any = PropTypes.any, lowcodeType: string | object = {}
|
||||
return lowcodeCheckType;
|
||||
}
|
||||
|
||||
const LowcodeTypes: any = {
|
||||
export const LowcodeTypes: any = {
|
||||
...PropTypes,
|
||||
define,
|
||||
};
|
||||
|
||||
(window as any).PropTypes = LowcodeTypes;
|
||||
(window as any).React.PropTypes = LowcodeTypes;
|
||||
if ((window as any).React) {
|
||||
(window as any).React.PropTypes = LowcodeTypes;
|
||||
}
|
||||
|
||||
// override primitive type checkers
|
||||
primitiveTypes.forEach((type) => {
|
||||
|
||||
@ -440,23 +440,23 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
}
|
||||
|
||||
private initialChildren(children: IPublicTypeNodeData | IPublicTypeNodeData[] | undefined): IPublicTypeNodeData[] {
|
||||
// FIXME! this is dirty code
|
||||
const { initialChildren } = this.componentMeta.advanced;
|
||||
|
||||
if (children == null) {
|
||||
const { initialChildren } = this.componentMeta.advanced;
|
||||
if (initialChildren) {
|
||||
if (typeof initialChildren === 'function') {
|
||||
return initialChildren(this.internalToShellNode()!) || [];
|
||||
}
|
||||
return initialChildren;
|
||||
}
|
||||
}
|
||||
if (Array.isArray(children)) {
|
||||
return children;
|
||||
} else if (children) {
|
||||
return [children];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (Array.isArray(children)) {
|
||||
return children;
|
||||
}
|
||||
|
||||
return [children];
|
||||
}
|
||||
|
||||
isContainer(): boolean {
|
||||
@ -1094,7 +1094,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可执行某action
|
||||
* 是否可执行某 action
|
||||
*/
|
||||
canPerformAction(actionName: string): boolean {
|
||||
const availableActions =
|
||||
|
||||
@ -290,10 +290,6 @@ export class Prop implements IProp, IPropParent {
|
||||
}
|
||||
|
||||
if (type === 'literal' || type === 'expression') {
|
||||
// TODO 后端改造之后删除此逻辑
|
||||
if (this._value === null && stage === IPublicEnumTransformStage.Save) {
|
||||
return '';
|
||||
}
|
||||
return this._value;
|
||||
}
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@ export interface ILowCodePluginContextPrivate {
|
||||
set workspace(workspace: IPublicApiWorkspace);
|
||||
set editorWindow(window: IPublicModelWindow);
|
||||
set registerLevel(level: IPublicEnumPluginRegisterLevel);
|
||||
set isPluginRegisteredInWorkspace(flag: boolean);
|
||||
}
|
||||
export interface ILowCodePluginContextApiAssembler {
|
||||
assembleApis(
|
||||
|
||||
@ -1,19 +1,50 @@
|
||||
function sequence(tasks, names, results, missing, recursive, nest) {
|
||||
interface ITaks {
|
||||
[key: string]: {
|
||||
name: string;
|
||||
dep: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export function sequence({
|
||||
tasks,
|
||||
names,
|
||||
results,
|
||||
missing,
|
||||
recursive,
|
||||
nest,
|
||||
parentName,
|
||||
}: {
|
||||
tasks: ITaks;
|
||||
names: string[];
|
||||
results: string[];
|
||||
missing: string[];
|
||||
recursive: string[][];
|
||||
nest: string[];
|
||||
parentName: string;
|
||||
}) {
|
||||
names.forEach((name) => {
|
||||
if (results.indexOf(name) !== -1) {
|
||||
return; // de-dup results
|
||||
}
|
||||
const node = tasks[name];
|
||||
if (!node) {
|
||||
missing.push(name);
|
||||
missing.push([parentName, name].filter((d => !!d)).join('.'));
|
||||
} else if (nest.indexOf(name) > -1) {
|
||||
nest.push(name);
|
||||
recursive.push(nest.slice(0));
|
||||
nest.pop(name);
|
||||
nest.pop();
|
||||
} else if (node.dep.length) {
|
||||
nest.push(name);
|
||||
sequence(tasks, node.dep, results, missing, recursive, nest); // recurse
|
||||
nest.pop(name);
|
||||
sequence({
|
||||
tasks,
|
||||
parentName: name,
|
||||
names: node.dep,
|
||||
results,
|
||||
missing,
|
||||
recursive,
|
||||
nest,
|
||||
}); // recurse
|
||||
nest.pop();
|
||||
}
|
||||
results.push(name);
|
||||
});
|
||||
@ -21,12 +52,19 @@ function sequence(tasks, names, results, missing, recursive, nest) {
|
||||
|
||||
// tasks: object with keys as task names
|
||||
// names: array of task names
|
||||
export default function (tasks, names) {
|
||||
let results = []; // the final sequence
|
||||
const missing = []; // missing tasks
|
||||
const recursive = []; // recursive task dependencies
|
||||
export default function (tasks: ITaks, names: string[]) {
|
||||
let results: string[] = []; // the final sequence
|
||||
const missing: string[] = []; // missing tasks
|
||||
const recursive: string[][] = []; // recursive task dependencies
|
||||
|
||||
sequence(tasks, names, results, missing, recursive, []);
|
||||
sequence({
|
||||
tasks,
|
||||
names,
|
||||
results,
|
||||
missing,
|
||||
recursive,
|
||||
nest: [],
|
||||
});
|
||||
|
||||
if (missing.length || recursive.length) {
|
||||
results = []; // results are incomplete at best, completely wrong at worst, remove them to avoid confusion
|
||||
|
||||
@ -54,7 +54,60 @@ describe('Node 方法测试', () => {
|
||||
project = null;
|
||||
});
|
||||
|
||||
it('condition group', () => {});
|
||||
// Case 1: When children is null
|
||||
test('initialChildren returns result of initialChildren function when children is null ', () => {
|
||||
const node = new Node(doc, { componentName: 'Button', props: { a: 1 } });
|
||||
const result = node.initialChildren(null);
|
||||
// 预期结果是一个空数组
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
// Case 2: When children is undefined
|
||||
test('initialChildren returns result of initialChildren function when children is null ', () => {
|
||||
const node = new Node(doc, { componentName: 'Button', props: { a: 1 } });
|
||||
const result = node.initialChildren(undefined);
|
||||
// 预期结果是一个空数组
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
// Case 3: When children is array
|
||||
test('initialChildren returns result of initialChildren function when children is null ', () => {
|
||||
const node = new Node(doc, { componentName: 'Button', props: { a: 1 } });
|
||||
const childrenArray = [{ id: 1, name: 'Child 1' }, { id: 2, name: 'Child 2' }];
|
||||
const result = node.initialChildren(childrenArray);
|
||||
// 预期结果是一个数组
|
||||
expect(result).toEqual(childrenArray);
|
||||
});
|
||||
|
||||
// Case 4: When children is not null and not an array
|
||||
test('initialChildren returns result of initialChildren function when children is null ', () => {
|
||||
const node = new Node(doc, { componentName: 'Button', props: { a: 1 } });
|
||||
const childObject = { id: 1, name: 'Child 1' };
|
||||
const result = node.initialChildren(childObject);
|
||||
// 预期结果是一个数组
|
||||
expect(result).toEqual([childObject]);
|
||||
});
|
||||
|
||||
// Case 5: When children 0
|
||||
test('initialChildren returns result of initialChildren function when children is null ', () => {
|
||||
const node = new Node(doc, { componentName: 'Button', props: { a: 1 } });
|
||||
const childObject = 0;
|
||||
const result = node.initialChildren(childObject);
|
||||
// 预期结果是一个数组
|
||||
expect(result).toEqual([0]);
|
||||
});
|
||||
|
||||
// Case 6: When children false
|
||||
test('initialChildren returns result of initialChildren function when children is null ', () => {
|
||||
const node = new Node(doc, { componentName: 'Button', props: { a: 1 } });
|
||||
const childObject = false;
|
||||
const result = node.initialChildren(childObject);
|
||||
// 预期结果是一个数组
|
||||
expect(result).toEqual([false]);
|
||||
});
|
||||
|
||||
|
||||
it('condition group', () => { });
|
||||
|
||||
it('getExtraProp / setExtraProp', () => {
|
||||
const firstBtn = doc.getNode('node_k1ow3cbn')!;
|
||||
@ -367,7 +420,7 @@ describe('Node 方法测试', () => {
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('addSlot / unlinkSlot / removeSlot', () => {});
|
||||
it('addSlot / unlinkSlot / removeSlot', () => { });
|
||||
|
||||
it('setProps', () => {
|
||||
const firstBtn = doc.getNode('node_k1ow3cbn')!;
|
||||
@ -407,7 +460,7 @@ describe('Node 方法测试', () => {
|
||||
designer.createComponentMeta(btnMetadata);
|
||||
const btn = doc.getNode('node_k1ow3cbn');
|
||||
// 从 componentMeta 中获取到 title 值
|
||||
expect(btn.title).toEqual({ type: 'i18n', 'zh-CN': '按钮', 'en-US': 'Button' } );
|
||||
expect(btn.title).toEqual({ type: 'i18n', 'zh-CN': '按钮', 'en-US': 'Button' });
|
||||
// 从 extraProp 中获取值
|
||||
btn.setExtraProp('title', 'hello button');
|
||||
expect(btn.title).toBe('hello button');
|
||||
@ -546,7 +599,7 @@ describe('Node 方法测试', () => {
|
||||
expect(comparePosition(firstBtn, firstCard)).toBe(PositionNO.BeforeOrAfter);
|
||||
});
|
||||
|
||||
it('getZLevelTop', () => {});
|
||||
it('getZLevelTop', () => { });
|
||||
it('propsData', () => {
|
||||
expect(new Node(doc, { componentName: 'Leaf' }).propsData).toBeNull();
|
||||
expect(new Node(doc, { componentName: 'Fragment' }).propsData).toBeNull();
|
||||
|
||||
@ -136,7 +136,7 @@ describe('Prop 类测试', () => {
|
||||
expect(boolProp.export(IPublicEnumTransformStage.Save)).toBe(true);
|
||||
expect(strProp.export(IPublicEnumTransformStage.Save)).toBe('haha');
|
||||
expect(numProp.export(IPublicEnumTransformStage.Save)).toBe(1);
|
||||
expect(nullProp.export(IPublicEnumTransformStage.Save)).toBe('');
|
||||
expect(nullProp.export(IPublicEnumTransformStage.Save)).toBe(null);
|
||||
expect(nullProp.export(IPublicEnumTransformStage.Serilize)).toBe(null);
|
||||
expect(expProp.export(IPublicEnumTransformStage.Save)).toEqual({
|
||||
type: 'JSExpression',
|
||||
|
||||
16
packages/designer/tests/fixtures/schema/form.ts
vendored
16
packages/designer/tests/fixtures/schema/form.ts
vendored
@ -267,7 +267,7 @@ export default {
|
||||
labelTipsText: {
|
||||
type: 'i18n',
|
||||
use: 'zh-CN',
|
||||
'en-US': null,
|
||||
'en-US': '',
|
||||
'zh-CN': '',
|
||||
},
|
||||
},
|
||||
@ -337,7 +337,7 @@ export default {
|
||||
labelTipsText: {
|
||||
type: 'i18n',
|
||||
use: 'zh-CN',
|
||||
'en-US': null,
|
||||
'en-US': '',
|
||||
'zh-CN': '',
|
||||
},
|
||||
},
|
||||
@ -407,7 +407,7 @@ export default {
|
||||
labelTipsText: {
|
||||
type: 'i18n',
|
||||
use: 'zh-CN',
|
||||
'en-US': null,
|
||||
'en-US': '',
|
||||
'zh-CN': '',
|
||||
},
|
||||
},
|
||||
@ -489,7 +489,7 @@ export default {
|
||||
labelTipsText: {
|
||||
type: 'i18n',
|
||||
use: 'zh-CN',
|
||||
'en-US': null,
|
||||
'en-US': '',
|
||||
'zh-CN': '',
|
||||
},
|
||||
},
|
||||
@ -578,7 +578,7 @@ export default {
|
||||
labelTipsText: {
|
||||
type: 'i18n',
|
||||
use: 'zh-CN',
|
||||
'en-US': null,
|
||||
'en-US': '',
|
||||
'zh-CN': '',
|
||||
},
|
||||
searchDelay: 300,
|
||||
@ -697,7 +697,7 @@ export default {
|
||||
labelTipsText: {
|
||||
type: 'i18n',
|
||||
use: 'zh-CN',
|
||||
'en-US': null,
|
||||
'en-US': '',
|
||||
'zh-CN': '',
|
||||
},
|
||||
},
|
||||
@ -789,7 +789,7 @@ export default {
|
||||
labelTipsText: {
|
||||
type: 'i18n',
|
||||
use: 'zh-CN',
|
||||
'en-US': null,
|
||||
'en-US': '',
|
||||
'zh-CN': '',
|
||||
},
|
||||
},
|
||||
@ -871,7 +871,7 @@ export default {
|
||||
labelTipsText: {
|
||||
type: 'i18n',
|
||||
use: 'zh-CN',
|
||||
'en-US': null,
|
||||
'en-US': '',
|
||||
'zh-CN': '',
|
||||
},
|
||||
},
|
||||
|
||||
128
packages/designer/tests/plugin/sequencify.test.ts
Normal file
128
packages/designer/tests/plugin/sequencify.test.ts
Normal file
@ -0,0 +1,128 @@
|
||||
import sequencify, { sequence } from '../../src/plugin/sequencify';
|
||||
|
||||
describe('sequence', () => {
|
||||
it('handles tasks with no dependencies', () => {
|
||||
const tasks = {
|
||||
task1: { name: 'Task 1', dep: [] },
|
||||
task2: { name: 'Task 2', dep: [] }
|
||||
};
|
||||
const results = [];
|
||||
const missing = [];
|
||||
const recursive = [];
|
||||
sequence({ tasks, names: ['task1', 'task2'], results, missing, recursive, nest: [] });
|
||||
|
||||
expect(results).toEqual(['task1', 'task2']);
|
||||
expect(missing).toEqual([]);
|
||||
expect(recursive).toEqual([]);
|
||||
});
|
||||
|
||||
it('correctly orders tasks based on dependencies', () => {
|
||||
const tasks = {
|
||||
task1: { name: 'Task 1', dep: [] },
|
||||
task2: { name: 'Task 2', dep: ['task1'] }
|
||||
};
|
||||
const results = [];
|
||||
const missing = [];
|
||||
const recursive = [];
|
||||
sequence({ tasks, names: ['task2', 'task1'], results, missing, recursive, nest: [] });
|
||||
|
||||
expect(results).toEqual(['task1', 'task2']);
|
||||
expect(missing).toEqual([]);
|
||||
expect(recursive).toEqual([]);
|
||||
});
|
||||
|
||||
it('identifies missing tasks', () => {
|
||||
const tasks = {
|
||||
task1: { name: 'Task 1', dep: [] }
|
||||
};
|
||||
const results = [];
|
||||
const missing = [];
|
||||
const recursive = [];
|
||||
const nest = []
|
||||
sequence({ tasks, names: ['task2'], results, missing, recursive, nest });
|
||||
|
||||
expect(results).toEqual(['task2']);
|
||||
expect(missing).toEqual(['task2']);
|
||||
expect(recursive).toEqual([]);
|
||||
expect(nest).toEqual([]);
|
||||
});
|
||||
|
||||
it('detects recursive dependencies', () => {
|
||||
const tasks = {
|
||||
task1: { name: 'Task 1', dep: ['task2'] },
|
||||
task2: { name: 'Task 2', dep: ['task1'] }
|
||||
};
|
||||
const results = [];
|
||||
const missing = [];
|
||||
const recursive = [];
|
||||
const nest = []
|
||||
sequence({ tasks, names: ['task1', 'task2'], results, missing, recursive, nest });
|
||||
|
||||
expect(results).toEqual(['task1', 'task2', 'task1']);
|
||||
expect(missing).toEqual([]);
|
||||
expect(recursive).toEqual([['task1', 'task2', 'task1']]);
|
||||
expect(nest).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sequence', () => {
|
||||
|
||||
it('should return tasks in sequence without dependencies', () => {
|
||||
const tasks = {
|
||||
task1: { name: 'Task 1', dep: [] },
|
||||
task2: { name: 'Task 2', dep: [] },
|
||||
task3: { name: 'Task 3', dep: [] }
|
||||
};
|
||||
const names = ['task1', 'task2', 'task3'];
|
||||
const expected = {
|
||||
sequence: ['task1', 'task2', 'task3'],
|
||||
missingTasks: [],
|
||||
recursiveDependencies: []
|
||||
};
|
||||
expect(sequencify(tasks, names)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should handle tasks with dependencies', () => {
|
||||
const tasks = {
|
||||
task1: { name: 'Task 1', dep: [] },
|
||||
task2: { name: 'Task 2', dep: ['task1'] },
|
||||
task3: { name: 'Task 3', dep: ['task2'] }
|
||||
};
|
||||
const names = ['task3', 'task2', 'task1'];
|
||||
const expected = {
|
||||
sequence: ['task1', 'task2', 'task3'],
|
||||
missingTasks: [],
|
||||
recursiveDependencies: []
|
||||
};
|
||||
expect(sequencify(tasks, names)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should identify missing tasks', () => {
|
||||
const tasks = {
|
||||
task1: { name: 'Task 1', dep: [] },
|
||||
task2: { name: 'Task 2', dep: ['task3'] } // task3 is missing
|
||||
};
|
||||
const names = ['task1', 'task2'];
|
||||
const expected = {
|
||||
sequence: [],
|
||||
missingTasks: ['task2.task3'],
|
||||
recursiveDependencies: []
|
||||
};
|
||||
expect(sequencify(tasks, names)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should detect recursive dependencies', () => {
|
||||
const tasks = {
|
||||
task1: { name: 'Task 1', dep: ['task2'] },
|
||||
task2: { name: 'Task 2', dep: ['task1'] } // Recursive dependency
|
||||
};
|
||||
const names = ['task1', 'task2'];
|
||||
const expected = {
|
||||
sequence: [],
|
||||
missingTasks: [],
|
||||
recursiveDependencies: [['task1', 'task2', 'task1']]
|
||||
};
|
||||
expect(sequencify(tasks, names)).toEqual(expected);
|
||||
});
|
||||
|
||||
});
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-editor-core",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"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.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^4.1.1",
|
||||
"intl-messageformat": "^9.3.1",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-editor-skeleton",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "alibaba lowcode editor skeleton",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -19,10 +19,10 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.20.12",
|
||||
"@alilc/lowcode-designer": "1.2.2",
|
||||
"@alilc/lowcode-editor-core": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-designer": "1.2.3",
|
||||
"@alilc/lowcode-editor-core": "1.2.3",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
|
||||
@ -232,12 +232,8 @@ export class PanelView extends Component<{
|
||||
this.lastVisible = currentVisible;
|
||||
if (this.lastVisible) {
|
||||
panel.skeleton.postEvent(SkeletonEvents.PANEL_SHOW, panel.name, panel);
|
||||
// FIXME! remove this line
|
||||
panel.skeleton.postEvent('leftPanel.show' as any, panel.name, panel);
|
||||
} else {
|
||||
panel.skeleton.postEvent(SkeletonEvents.PANEL_HIDE, panel.name, panel);
|
||||
// FIXME! remove this line
|
||||
panel.skeleton.postEvent('leftPanel.hide' as any, panel.name, panel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
--color-icon-normal: @normal-alpha-4;
|
||||
--color-icon-hover: @normal-alpha-3;
|
||||
--color-icon-light: @normal-alpha-5;
|
||||
--color-icon-active: @brand-color-1;
|
||||
--color-icon-reverse: @white-alpha-1;
|
||||
--color-icon-disabled: @normal-alpha-6;
|
||||
@ -27,7 +28,6 @@
|
||||
--color-text-dark: darken(@dark-alpha-3, 10%);
|
||||
--color-text-light: lighten(@dark-alpha-3, 10%);
|
||||
--color-text-reverse: @white-alpha-2;
|
||||
--color-text-regular: @normal-alpha-2;
|
||||
--color-text-disabled: @gray-light;
|
||||
|
||||
--color-field-label: @dark-alpha-4;
|
||||
@ -56,10 +56,11 @@
|
||||
--color-pane-background: @white-alpha-1;
|
||||
--color-block-background-normal: @white-alpha-1;
|
||||
--color-block-background-light: @normal-alpha-9;
|
||||
--color-block-background-shallow: @normal-alpha-8;
|
||||
--color-block-background-dark: @normal-alpha-7;
|
||||
--color-block-background-shallow: @normal-alpha-8;
|
||||
--color-block-background-disabled: @normal-alpha-6;
|
||||
--color-block-background-active: @brand-color-1-7;
|
||||
--color-block-background-active: @brand-color-1;
|
||||
--color-block-background-active-light: @brand-color-1-7;
|
||||
--color-block-background-warning: @brand-warning-alpha-7;
|
||||
--color-block-background-error: @brand-danger-alpha-7;
|
||||
--color-block-background-success: @brand-success-alpha-7;
|
||||
@ -68,6 +69,8 @@
|
||||
--color-layer-tooltip-background: rgba(44,47,51,0.8);
|
||||
--color-background: #edeff3;
|
||||
|
||||
--color-canvas-detecting-background: rgba(0,121,242,.04);
|
||||
|
||||
--pane-title-bg-color: rgba(31,56,88,.04);
|
||||
}
|
||||
|
||||
@ -87,4 +90,5 @@
|
||||
--color-function-error-light: lighten(@brand-danger, 10%);
|
||||
--color-function-purple: rgb(144, 94, 190);
|
||||
--color-function-brown: #7b605b;
|
||||
--color-text-regular: @normal-alpha-2;
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
--popup-border-radius: @popup-border-radius;
|
||||
|
||||
--left-area-width: 48px;
|
||||
--workspace-left-area-width: 48px;
|
||||
--right-area-width: 300px;
|
||||
--top-area-height: 48px;
|
||||
--toolbar-height: 36px;
|
||||
@ -65,16 +66,16 @@ body {
|
||||
}
|
||||
}
|
||||
> .lc-panel-title {
|
||||
height: 48px;
|
||||
font-size: 16px;
|
||||
padding: 0 15px;
|
||||
height: var(--pane-title-height, 48px);
|
||||
font-size: var(--pane-title-font-size, 16px);
|
||||
padding: var(--pane-title-padding, 0 15px);
|
||||
color: var(--color-title, #0f1726);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.lc-panel-body {
|
||||
position: absolute;
|
||||
top: 48px;
|
||||
top: var(--pane-title-height, 48px);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
@ -104,6 +105,7 @@ body {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
|
||||
&.active {
|
||||
z-index: 999;
|
||||
@ -233,7 +235,7 @@ body {
|
||||
.lc-pane-icon-close {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 14px;
|
||||
top: calc(var(--pane-title-height, 48px) / 2 - 10px);
|
||||
height: auto;
|
||||
z-index: 2;
|
||||
.next-icon {
|
||||
@ -246,7 +248,7 @@ body {
|
||||
.lc-pane-icon-float {
|
||||
position: absolute;
|
||||
right: 38px;
|
||||
top: 14px;
|
||||
top: calc(var(--pane-title-height, 48px) / 2 - 10px);
|
||||
height: auto;
|
||||
z-index: 2;
|
||||
svg {
|
||||
@ -273,7 +275,7 @@ body {
|
||||
}
|
||||
.lc-left-area, .lc-workspace-left-area {
|
||||
height: 100%;
|
||||
width: var(--left-area-width);
|
||||
width: var(--workspace-left-area-width, --left-area-width);
|
||||
display: none;
|
||||
flex-shrink: 0;
|
||||
flex-direction: column;
|
||||
@ -365,8 +367,8 @@ body {
|
||||
.lc-toolbar {
|
||||
display: flex;
|
||||
height: var(--toolbar-height);
|
||||
background-color: var(--color-pane-background);
|
||||
padding: 8px 16px;
|
||||
background-color: var(--color-toolbar-background, var(--color-pane-background));
|
||||
padding: var(--toolbar-padding, 8px 16px);
|
||||
.lc-toolbar-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -442,6 +444,10 @@ body {
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
|
||||
> .lc-left-float-pane {
|
||||
left: calc(var(--workspace-left-area-width, var(--left-area-width)) + 1px);
|
||||
}
|
||||
|
||||
.lc-workspace-workbench-center {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
@ -451,8 +457,8 @@ body {
|
||||
.lc-toolbar {
|
||||
display: flex;
|
||||
height: var(--toolbar-height);
|
||||
background-color: var(--color-pane-background);
|
||||
padding: 8px 16px;
|
||||
background-color: var(--color-toolbar-background, var(--color-pane-background));
|
||||
padding: var(--toolbar-padding, 8px 16px);
|
||||
.lc-toolbar-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
@ -28,6 +28,7 @@ import {
|
||||
IPublicTypeWidgetConfigArea,
|
||||
IPublicTypeSkeletonConfig,
|
||||
IPublicApiSkeleton,
|
||||
IPublicTypeConfigTransducer,
|
||||
} from '@alilc/lowcode-types';
|
||||
|
||||
const logger = new Logger({ level: 'warn', bizName: 'skeleton' });
|
||||
@ -111,6 +112,8 @@ export interface ISkeleton extends Omit<IPublicApiSkeleton,
|
||||
export class Skeleton implements ISkeleton {
|
||||
private panels = new Map<string, Panel>();
|
||||
|
||||
private configTransducers: IPublicTypeConfigTransducer[] = [];
|
||||
|
||||
private containers = new Map<string, WidgetContainer<any>>();
|
||||
|
||||
readonly leftArea: Area<DockConfig | PanelDockConfig | DialogDockConfig>;
|
||||
@ -448,11 +451,35 @@ export class Skeleton implements ISkeleton {
|
||||
return restConfig;
|
||||
}
|
||||
|
||||
registerConfigTransducer(
|
||||
transducer: IPublicTypeConfigTransducer,
|
||||
level = 100,
|
||||
id?: string,
|
||||
) {
|
||||
transducer.level = level;
|
||||
transducer.id = id;
|
||||
const i = this.configTransducers.findIndex((item) => item.level != null && item.level > level);
|
||||
if (i < 0) {
|
||||
this.configTransducers.push(transducer);
|
||||
} else {
|
||||
this.configTransducers.splice(i, 0, transducer);
|
||||
}
|
||||
}
|
||||
|
||||
getRegisteredConfigTransducers(): IPublicTypeConfigTransducer[] {
|
||||
return this.configTransducers;
|
||||
}
|
||||
|
||||
add(config: IPublicTypeSkeletonConfig, extraConfig?: Record<string, any>): IWidget | Widget | Panel | Stage | Dock | PanelDock | undefined {
|
||||
const parsedConfig = {
|
||||
const registeredTransducers = this.getRegisteredConfigTransducers();
|
||||
|
||||
const parsedConfig = registeredTransducers.reduce((prevConfig, current) => {
|
||||
return current(prevConfig);
|
||||
}, {
|
||||
...this.parseConfig(config),
|
||||
...extraConfig,
|
||||
};
|
||||
});
|
||||
|
||||
let { area } = parsedConfig;
|
||||
if (!area) {
|
||||
if (parsedConfig.type === 'Panel') {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-engine",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "An enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系",
|
||||
"main": "lib/engine-core.js",
|
||||
"module": "es/engine-core.js",
|
||||
@ -19,15 +19,15 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.12",
|
||||
"@alilc/lowcode-designer": "1.2.2",
|
||||
"@alilc/lowcode-editor-core": "1.2.2",
|
||||
"@alilc/lowcode-editor-skeleton": "1.2.2",
|
||||
"@alilc/lowcode-designer": "1.2.3",
|
||||
"@alilc/lowcode-editor-core": "1.2.3",
|
||||
"@alilc/lowcode-editor-skeleton": "1.2.3",
|
||||
"@alilc/lowcode-engine-ext": "^1.0.0",
|
||||
"@alilc/lowcode-plugin-designer": "1.2.2",
|
||||
"@alilc/lowcode-plugin-outline-pane": "1.2.2",
|
||||
"@alilc/lowcode-shell": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-workspace": "1.2.2",
|
||||
"@alilc/lowcode-plugin-designer": "1.2.3",
|
||||
"@alilc/lowcode-plugin-outline-pane": "1.2.3",
|
||||
"@alilc/lowcode-shell": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"@alilc/lowcode-workspace": "1.2.3",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
|
||||
@ -54,7 +54,7 @@ import {
|
||||
} from '@alilc/lowcode-shell';
|
||||
import { isPlainObject } from '@alilc/lowcode-utils';
|
||||
import './modules/live-editing';
|
||||
import classes from './modules/classes';
|
||||
import * as classes from './modules/classes';
|
||||
import symbols from './modules/symbols';
|
||||
import { componentMetaParser } from './inner-plugins/component-meta-parser';
|
||||
import { setterRegistry } from './inner-plugins/setter-registry';
|
||||
@ -139,6 +139,7 @@ const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
|
||||
context.logger = new Logger({ level: 'warn', bizName: `plugin:${pluginName}` });
|
||||
context.workspace = workspace;
|
||||
context.registerLevel = IPublicEnumPluginRegisterLevel.Default;
|
||||
context.isPluginRegisteredInWorkspace = false;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-ignitor",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "点火器,bootstrap lce project",
|
||||
"main": "lib/index.js",
|
||||
"private": true,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-plugin-designer",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "alibaba lowcode editor designer plugin",
|
||||
"files": [
|
||||
"es",
|
||||
@ -18,9 +18,9 @@
|
||||
],
|
||||
"author": "xiayang.xy",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.2.2",
|
||||
"@alilc/lowcode-editor-core": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-designer": "1.2.3",
|
||||
"@alilc/lowcode-editor-core": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"react": "^16.8.1",
|
||||
"react-dom": "^16.8.1"
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-plugin-outline-pane",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "Outline pane for Ali lowCode engine",
|
||||
"files": [
|
||||
"es",
|
||||
@ -13,8 +13,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-types": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16",
|
||||
"react-dom": "^16.7.0",
|
||||
|
||||
@ -41,22 +41,19 @@ export class TreeMaster {
|
||||
this.initEvent();
|
||||
if (pluginContext.registerLevel === IPublicEnumPluginRegisterLevel.Workspace) {
|
||||
this.setPluginContext(workspace.window?.currentEditorView);
|
||||
workspace.onWindowRendererReady(() => {
|
||||
this.setPluginContext(workspace.window?.currentEditorView);
|
||||
let dispose: IPublicTypeDisposable | undefined;
|
||||
const windowViewTypeChangeEvent = () => {
|
||||
dispose = workspace.window?.onChangeViewType(() => {
|
||||
this.setPluginContext(workspace.window?.currentEditorView);
|
||||
});
|
||||
};
|
||||
|
||||
windowViewTypeChangeEvent();
|
||||
|
||||
workspace.onChangeActiveWindow(() => {
|
||||
windowViewTypeChangeEvent();
|
||||
let dispose: IPublicTypeDisposable | undefined;
|
||||
const windowViewTypeChangeEvent = () => {
|
||||
dispose = workspace.window?.onChangeViewType(() => {
|
||||
this.setPluginContext(workspace.window?.currentEditorView);
|
||||
dispose && dispose();
|
||||
});
|
||||
};
|
||||
|
||||
windowViewTypeChangeEvent();
|
||||
|
||||
workspace.onChangeActiveWindow(() => {
|
||||
this.setPluginContext(workspace.window?.currentEditorView);
|
||||
dispose && dispose();
|
||||
windowViewTypeChangeEvent();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
}
|
||||
|
||||
.lc-outline-filter-icon {
|
||||
background: var(--color-block-background-shallow, #ebecf0);
|
||||
background: var(--color-block-background-light, #ebecf0);
|
||||
border: 1px solid var(--color-field-border, #c4c6cf);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-rax-renderer",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"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.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-renderer-core": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"rax-find-dom-node": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-rax-simulator-renderer",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"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.2.2",
|
||||
"@alilc/lowcode-rax-renderer": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-designer": "1.2.3",
|
||||
"@alilc/lowcode-rax-renderer": "1.2.3",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"classnames": "^2.2.6",
|
||||
"driver-universal": "^3.1.3",
|
||||
"history": "^5.0.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-react-renderer",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"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.2.2"
|
||||
"@alilc/lowcode-renderer-core": "1.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-react-simulator-renderer",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "react simulator renderer for alibaba lowcode designer",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -17,10 +17,10 @@
|
||||
"test:cov": "build-scripts test --config build.test.json --jest-coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.2.2",
|
||||
"@alilc/lowcode-react-renderer": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-designer": "1.2.3",
|
||||
"@alilc/lowcode-react-renderer": "1.2.3",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"classnames": "^2.2.6",
|
||||
"mobx": "^6.3.0",
|
||||
"mobx-react": "^7.2.0",
|
||||
|
||||
1
packages/renderer-core/babel.config.js
Normal file
1
packages/renderer-core/babel.config.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('../../babel.config');
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-renderer-core",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "renderer core",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
@ -16,8 +16,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-datasource-engine": "^1.0.0",
|
||||
"@alilc/lowcode-types": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^4.1.1",
|
||||
"fetch-jsonp": "^1.1.3",
|
||||
@ -32,7 +32,7 @@
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@alifd/next": "^1.26.0",
|
||||
"@alilc/lowcode-designer": "1.2.2",
|
||||
"@alilc/lowcode-designer": "1.2.3",
|
||||
"@babel/plugin-transform-typescript": "^7.16.8",
|
||||
"@testing-library/react": "^11.2.2",
|
||||
"@types/classnames": "^2.2.11",
|
||||
|
||||
@ -4,6 +4,7 @@ import { isReactComponent, cloneEnumerableProperty } from '@alilc/lowcode-utils'
|
||||
import { debounce } from '../utils/common';
|
||||
import adapter from '../adapter';
|
||||
import * as types from '../types/index';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
export interface IComponentHocInfo {
|
||||
schema: any;
|
||||
@ -183,7 +184,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
}
|
||||
|
||||
if (!isReactComponent(Comp)) {
|
||||
console.error(`${schema.componentName} component may be has errors: `, Comp);
|
||||
logger.error(`${schema.componentName} component may be has errors: `, Comp);
|
||||
}
|
||||
|
||||
initRerenderEvent({
|
||||
|
||||
@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
||||
import baseRendererFactory from './base';
|
||||
import { isEmpty } from '../utils';
|
||||
import { IRendererAppHelper, IBaseRendererProps, IBaseRenderComponent } from '../types';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
export default function addonRendererFactory(): IBaseRenderComponent {
|
||||
const BaseRenderer = baseRendererFactory();
|
||||
@ -32,7 +33,7 @@ export default function addonRendererFactory(): IBaseRenderComponent {
|
||||
const schema = props.__schema || {};
|
||||
this.state = this.__parseData(schema.state || {});
|
||||
if (isEmpty(props.config) || !props.config?.addonKey) {
|
||||
console.warn('lce addon has wrong config');
|
||||
logger.warn('lce addon has wrong config');
|
||||
this.setState({
|
||||
__hasError: true,
|
||||
});
|
||||
|
||||
@ -56,14 +56,14 @@ export function executeLifeCycleMethod(context: any, schema: IPublicTypeNodeSche
|
||||
}
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
console.error(`生命周期${method}类型不符`, fn);
|
||||
logger.error(`生命周期${method}类型不符`, fn);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
return fn.apply(context, args);
|
||||
} catch (e) {
|
||||
console.error(`[${schema.componentName}]生命周期${method}出错`, e);
|
||||
logger.error(`[${schema.componentName}]生命周期${method}出错`, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,7 +182,8 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
__afterInit(_props: IBaseRendererProps) { }
|
||||
|
||||
static getDerivedStateFromProps(props: IBaseRendererProps, state: any) {
|
||||
return executeLifeCycleMethod(this, props?.__schema, 'getDerivedStateFromProps', [props, state], props.thisRequiredInJSE);
|
||||
const result = executeLifeCycleMethod(this, props?.__schema, 'getDerivedStateFromProps', [props, state], props.thisRequiredInJSE);
|
||||
return result === undefined ? null : result;
|
||||
}
|
||||
|
||||
async getSnapshotBeforeUpdate(...args: any[]) {
|
||||
@ -208,7 +209,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
|
||||
async componentDidCatch(...args: any[]) {
|
||||
this.__executeLifeCycleMethod('componentDidCatch', args);
|
||||
console.warn(args);
|
||||
logger.warn(args);
|
||||
}
|
||||
|
||||
reloadDataSource = () => new Promise((resolve, reject) => {
|
||||
@ -278,7 +279,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
value = this.__parseExpression(value, this);
|
||||
}
|
||||
if (typeof value !== 'function') {
|
||||
console.error(`custom method ${key} can not be parsed to a valid function`, value);
|
||||
logger.error(`custom method ${key} can not be parsed to a valid function`, value);
|
||||
return;
|
||||
}
|
||||
this[key] = value.bind(this);
|
||||
@ -369,7 +370,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
this.setLocale = (loc: string) => {
|
||||
const setLocaleFn = this.appHelper?.utils?.i18n?.setLocale;
|
||||
if (!setLocaleFn || typeof setLocaleFn !== 'function') {
|
||||
console.warn('initI18nAPIs Failed, i18n only works when appHelper.utils.i18n.setLocale() exists');
|
||||
logger.warn('initI18nAPIs Failed, i18n only works when appHelper.utils.i18n.setLocale() exists');
|
||||
return undefined;
|
||||
}
|
||||
return setLocaleFn(loc);
|
||||
@ -428,7 +429,14 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
|
||||
__createDom = () => {
|
||||
const { __schema, __ctx, __components = {} } = this.props;
|
||||
const scope: any = {};
|
||||
// merge defaultProps
|
||||
const scopeProps = {
|
||||
...__schema.defaultProps,
|
||||
...this.props,
|
||||
};
|
||||
const scope: any = {
|
||||
props: scopeProps,
|
||||
};
|
||||
scope.__proto__ = __ctx || this;
|
||||
|
||||
const _children = getSchemaChildren(__schema);
|
||||
@ -527,7 +535,7 @@ 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);
|
||||
logger.error(`${schema.componentName} component is not found in components list! component list is:`, components || this.props.__container?.components);
|
||||
return engine.createElement(
|
||||
engine.getNotFoundComponent(),
|
||||
{
|
||||
@ -749,7 +757,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
|
||||
__createLoopVirtualDom = (schema: IPublicTypeNodeSchema, scope: any, parentInfo: INodeInfo, idx: number | string) => {
|
||||
if (isFileSchema(schema)) {
|
||||
console.warn('file type not support Loop');
|
||||
logger.warn('file type not support Loop');
|
||||
return null;
|
||||
}
|
||||
if (!Array.isArray(schema.loop)) {
|
||||
@ -901,9 +909,6 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
});
|
||||
return checkProps(res);
|
||||
}
|
||||
if (typeof props === 'string') {
|
||||
return checkProps(props.trim());
|
||||
}
|
||||
return checkProps(props);
|
||||
};
|
||||
|
||||
|
||||
@ -46,26 +46,5 @@ export default function componentRendererFactory(): IBaseRenderComponent {
|
||||
|
||||
return this.__renderComp(Component, this.__renderContextProvider({ compContext: this }));
|
||||
}
|
||||
|
||||
getComponentName() {
|
||||
return this.props?.componentName;
|
||||
}
|
||||
|
||||
/** 需要重载下面几个方法,如果在低代码组件中绑定了对应的生命周期时会出现死循环 */
|
||||
componentDidMount() {
|
||||
this.__debug(`componentDidMount - ${this.getComponentName()}`);
|
||||
}
|
||||
getSnapshotBeforeUpdate() {
|
||||
this.__debug(`getSnapshotBeforeUpdate - ${this.getComponentName()}`);
|
||||
}
|
||||
componentDidUpdate() {
|
||||
this.__debug(`componentDidUpdate - ${this.getComponentName()}`);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.__debug(`componentWillUnmount - ${this.getComponentName()}`);
|
||||
}
|
||||
componentDidCatch() {
|
||||
this.__debug(`componentDidCatch - ${this.getComponentName()}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { IBaseRenderComponent } from '../types';
|
||||
import logger from '../utils/logger';
|
||||
import baseRendererFactory from './base';
|
||||
|
||||
export default function tempRendererFactory(): IBaseRenderComponent {
|
||||
@ -41,7 +42,7 @@ export default function tempRendererFactory(): IBaseRenderComponent {
|
||||
}
|
||||
|
||||
async componentDidCatch(e: any) {
|
||||
console.warn(e);
|
||||
logger.warn(e);
|
||||
this.__debug(`componentDidCatch - ${this.props.__schema.fileName}`);
|
||||
}
|
||||
|
||||
|
||||
@ -183,13 +183,13 @@ export function transformArrayToMap(arr: any[], key: string, overwrite = true) {
|
||||
return res;
|
||||
}
|
||||
|
||||
export function checkPropTypes(value: any, name: string, rule: any, componentName: string) {
|
||||
export function checkPropTypes(value: any, name: string, rule: any, componentName: string): boolean {
|
||||
let ruleFunction = rule;
|
||||
if (typeof rule === 'string') {
|
||||
ruleFunction = new Function(`"use strict"; const PropTypes = arguments[0]; return ${rule}`)(PropTypes2);
|
||||
}
|
||||
if (!ruleFunction || typeof ruleFunction !== 'function') {
|
||||
console.warn('checkPropTypes should have a function type rule argument');
|
||||
logger.warn('checkPropTypes should have a function type rule argument');
|
||||
return true;
|
||||
}
|
||||
const err = ruleFunction(
|
||||
@ -203,7 +203,7 @@ export function checkPropTypes(value: any, name: string, rule: any, componentNam
|
||||
ReactPropTypesSecret,
|
||||
);
|
||||
if (err) {
|
||||
console.warn(err);
|
||||
logger.warn(err);
|
||||
}
|
||||
return !err;
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ export class DataHelper {
|
||||
}
|
||||
const { headers, ...otherProps } = otherOptionsObj || {};
|
||||
if (!req) {
|
||||
console.warn(`getDataSource API named ${id} not exist`);
|
||||
logger.warn(`getDataSource API named ${id} not exist`);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ export class DataHelper {
|
||||
try {
|
||||
callbackFn && callbackFn(res && res[id]);
|
||||
} catch (e) {
|
||||
console.error('load请求回调函数报错', e);
|
||||
logger.error('load请求回调函数报错', e);
|
||||
}
|
||||
return res && res[id];
|
||||
})
|
||||
@ -223,7 +223,7 @@ export class DataHelper {
|
||||
try {
|
||||
callbackFn && callbackFn(null, err);
|
||||
} catch (e) {
|
||||
console.error('load请求回调函数报错', e);
|
||||
logger.error('load请求回调函数报错', e);
|
||||
}
|
||||
return err;
|
||||
});
|
||||
@ -300,9 +300,9 @@ export class DataHelper {
|
||||
return dataHandlerFun.call(this.host, data, error);
|
||||
} catch (e) {
|
||||
if (id) {
|
||||
console.error(`[${id}]单个请求数据处理函数运行出错`, e);
|
||||
logger.error(`[${id}]单个请求数据处理函数运行出错`, e);
|
||||
} else {
|
||||
console.error('请求数据处理函数运行出错', e);
|
||||
logger.error('请求数据处理函数运行出错', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// @ts-nocheck
|
||||
import factoryWithTypeCheckers from 'prop-types/factoryWithTypeCheckers';
|
||||
import {
|
||||
isSchema,
|
||||
isFileSchema,
|
||||
@ -18,9 +18,14 @@ import {
|
||||
parseThisRequiredExpression,
|
||||
parseI18n,
|
||||
parseData,
|
||||
checkPropTypes,
|
||||
} from '../../src/utils/common';
|
||||
import logger from '../../src/utils/logger';
|
||||
|
||||
var ReactIs = require('react-is');
|
||||
|
||||
const PropTypes = factoryWithTypeCheckers(ReactIs.isElement, true);
|
||||
|
||||
describe('test isSchema', () => {
|
||||
it('should be false when empty value is passed', () => {
|
||||
expect(isSchema(null)).toBeFalsy();
|
||||
@ -461,4 +466,37 @@ describe('test parseData ', () => {
|
||||
expect(result.__privateKey).toBeUndefined();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkPropTypes', () => {
|
||||
it('should validate correctly with valid prop type', () => {
|
||||
expect(checkPropTypes(123, 'age', PropTypes.number, 'TestComponent')).toBe(true);
|
||||
expect(checkPropTypes('123', 'age', PropTypes.string, 'TestComponent')).toBe(true);
|
||||
});
|
||||
|
||||
it('should log a warning and return false with invalid prop type', () => {
|
||||
expect(checkPropTypes(123, 'age', PropTypes.string, 'TestComponent')).toBe(false);
|
||||
expect(checkPropTypes('123', 'age', PropTypes.number, 'TestComponent')).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle custom rule functions correctly', () => {
|
||||
const customRule = (props, propName) => {
|
||||
if (props[propName] !== 123) {
|
||||
return new Error('Invalid value');
|
||||
}
|
||||
};
|
||||
const result = checkPropTypes(123, 'customProp', customRule, 'TestComponent');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
it('should interpret and validate a rule given as a string', () => {
|
||||
const result = checkPropTypes(123, 'age', 'PropTypes.number', 'TestComponent');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should log a warning for invalid rule type', () => {
|
||||
const result = checkPropTypes(123, 'age', 123, 'TestComponent');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
@ -346,11 +346,6 @@ describe('test DataHelper ', () => {
|
||||
result = dataHelper.handleData('fullConfigGet', mockDataHandler, { data: 'mockDataValue' }, null);
|
||||
expect(result).toStrictEqual({ data: 'mockDataValue' });
|
||||
|
||||
// test exception
|
||||
const mockError = jest.fn();
|
||||
const orginalConsole = global.console;
|
||||
global.console = { error: mockError };
|
||||
|
||||
// exception with id
|
||||
mockDataHandler = {
|
||||
type: 'JSFunction',
|
||||
@ -358,7 +353,6 @@ describe('test DataHelper ', () => {
|
||||
};
|
||||
result = dataHelper.handleData('fullConfigGet', mockDataHandler, { data: 'mockDataValue' }, null);
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockError).toBeCalledWith('[fullConfigGet]单个请求数据处理函数运行出错', expect.anything());
|
||||
|
||||
// exception without id
|
||||
mockDataHandler = {
|
||||
@ -367,12 +361,8 @@ describe('test DataHelper ', () => {
|
||||
};
|
||||
result = dataHelper.handleData(null, mockDataHandler, { data: 'mockDataValue' }, null);
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockError).toBeCalledWith('请求数据处理函数运行出错', expect.anything());
|
||||
|
||||
global.console = orginalConsole;
|
||||
});
|
||||
|
||||
|
||||
it('updateConfig should work', () => {
|
||||
const mockHost = { stateA: 'aValue'};
|
||||
const mockDataSourceConfig = {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-shell",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "Shell Layer for AliLowCodeEngine",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -13,12 +13,12 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alilc/lowcode-designer": "1.2.2",
|
||||
"@alilc/lowcode-editor-core": "1.2.2",
|
||||
"@alilc/lowcode-editor-skeleton": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.2",
|
||||
"@alilc/lowcode-utils": "1.2.2",
|
||||
"@alilc/lowcode-workspace": "1.2.2",
|
||||
"@alilc/lowcode-designer": "1.2.3",
|
||||
"@alilc/lowcode-editor-core": "1.2.3",
|
||||
"@alilc/lowcode-editor-skeleton": "1.2.3",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"@alilc/lowcode-utils": "1.2.3",
|
||||
"@alilc/lowcode-workspace": "1.2.3",
|
||||
"classnames": "^2.2.6",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-react-16": "^1.15.5",
|
||||
|
||||
@ -4,7 +4,7 @@ import {
|
||||
SkeletonEvents,
|
||||
} from '@alilc/lowcode-editor-skeleton';
|
||||
import { skeletonSymbol } from '../symbols';
|
||||
import { IPublicApiSkeleton, IPublicModelSkeletonItem, IPublicTypeDisposable, IPublicTypeSkeletonConfig, IPublicTypeWidgetConfigArea } from '@alilc/lowcode-types';
|
||||
import { IPublicApiSkeleton, IPublicModelSkeletonItem, IPublicTypeConfigTransducer, IPublicTypeDisposable, IPublicTypeSkeletonConfig, IPublicTypeWidgetConfigArea } from '@alilc/lowcode-types';
|
||||
import { getLogger } from '@alilc/lowcode-utils';
|
||||
import { SkeletonItem } from '../model/skeleton-item';
|
||||
|
||||
@ -208,6 +208,10 @@ export class Skeleton implements IPublicApiSkeleton {
|
||||
});
|
||||
return () => editor.eventBus.off(SkeletonEvents.WIDGET_HIDE, listener);
|
||||
}
|
||||
|
||||
registerConfigTransducer(fn: IPublicTypeConfigTransducer, level: number, id?: string) {
|
||||
this[skeletonSymbol].registerConfigTransducer(fn, level, id);
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeArea(area: IPublicTypeWidgetConfigArea | undefined): 'leftArea' | 'rightArea' | 'topArea' | 'toolbar' | 'mainArea' | 'bottomArea' | 'leftFixedArea' | 'leftFloatArea' | 'stages' | 'subTopArea' {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-types",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "Types for Ali lowCode engine",
|
||||
"files": [
|
||||
"es",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { IPublicModelSkeletonItem } from '../model';
|
||||
import { IPublicTypeDisposable, IPublicTypeSkeletonConfig } from '../type';
|
||||
import { IPublicTypeConfigTransducer, IPublicTypeDisposable, IPublicTypeSkeletonConfig } from '../type';
|
||||
|
||||
export interface IPublicApiSkeleton {
|
||||
|
||||
@ -114,4 +114,21 @@ export interface IPublicApiSkeleton {
|
||||
* @returns
|
||||
*/
|
||||
onHideWidget(listener: (...args: any[]) => void): IPublicTypeDisposable;
|
||||
|
||||
/**
|
||||
* 注册一个面板的配置转换器(transducer)。
|
||||
* Registers a configuration transducer for a panel.
|
||||
* @param {IPublicTypeConfigTransducer} transducer
|
||||
* - 要注册的转换器函数。该函数接受一个配置对象(类型为 IPublicTypeSkeletonConfig)作为输入,并返回修改后的配置对象。
|
||||
* - The transducer function to be registered. This function takes a configuration object (of type IPublicTypeSkeletonConfig) as input and returns a modified configuration object.
|
||||
*
|
||||
* @param {number} level
|
||||
* - 转换器的优先级。优先级较高的转换器会先执行。
|
||||
* - The priority level of the transducer. Transducers with higher priority levels are executed first.
|
||||
*
|
||||
* @param {string} [id]
|
||||
* - (可选)转换器的唯一标识符。用于在需要时引用或操作特定的转换器。
|
||||
* - (Optional) A unique identifier for the transducer. Used for referencing or manipulating a specific transducer when needed.
|
||||
*/
|
||||
registerConfigTransducer(transducer: IPublicTypeConfigTransducer, level: number, id?: string): void;
|
||||
}
|
||||
|
||||
@ -108,6 +108,8 @@ export interface IPublicModelPluginContext {
|
||||
*/
|
||||
get registerLevel(): IPublicEnumPluginRegisterLevel;
|
||||
|
||||
get isPluginRegisteredInWorkspace(): boolean;
|
||||
|
||||
get editorWindow(): IPublicModelWindow;
|
||||
}
|
||||
|
||||
|
||||
9
packages/types/src/shell/type/config-transducer.ts
Normal file
9
packages/types/src/shell/type/config-transducer.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { IPublicTypeSkeletonConfig } from '.';
|
||||
|
||||
export interface IPublicTypeConfigTransducer {
|
||||
(prev: IPublicTypeSkeletonConfig): IPublicTypeSkeletonConfig;
|
||||
|
||||
level?: number;
|
||||
|
||||
id?: string;
|
||||
}
|
||||
@ -91,3 +91,4 @@ export * from './hotkey-callback-config';
|
||||
export * from './hotkey-callbacks';
|
||||
export * from './scrollable';
|
||||
export * from './simulator-renderer';
|
||||
export * from './config-transducer';
|
||||
@ -1,5 +1,5 @@
|
||||
export interface IPublicTypePluginConfig {
|
||||
init(): Promise<void>;
|
||||
destroy?(): Promise<void>;
|
||||
init(): Promise<void> | void;
|
||||
destroy?(): Promise<void> | void;
|
||||
exports?(): any;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { IPublicTypePropConfig } from './';
|
||||
|
||||
export type IPublicTypePropType = IPublicTypeBasicType | IPublicTypeRequiredType | IPublicTypeComplexType;
|
||||
export type IPublicTypeBasicType = 'array' | 'bool' | 'func' | 'number' | 'object' | 'string' | 'node' | 'element' | 'any';
|
||||
export type IPublicTypeComplexType = IPublicTypeOneOf | IPublicTypeOneOfType | IPublicTypeArrayOf | IPublicTypeObjectOf | IPublicTypeShape | IPublicTypeExact;
|
||||
export type IPublicTypeComplexType = IPublicTypeOneOf | IPublicTypeOneOfType | IPublicTypeArrayOf | IPublicTypeObjectOf | IPublicTypeShape | IPublicTypeExact | IPublicTypeInstanceOf;
|
||||
|
||||
export interface IPublicTypeRequiredType {
|
||||
type: IPublicTypeBasicType;
|
||||
@ -40,3 +40,9 @@ export interface IPublicTypeExact {
|
||||
value: IPublicTypePropConfig[];
|
||||
isRequired?: boolean;
|
||||
}
|
||||
|
||||
export interface IPublicTypeInstanceOf {
|
||||
type: 'instanceOf';
|
||||
value: IPublicTypePropConfig;
|
||||
isRequired?: boolean;
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import React from 'react';
|
||||
import { IPublicTypeEditorView } from './editor-view';
|
||||
|
||||
export interface IPublicResourceTypeConfig {
|
||||
@ -6,7 +7,7 @@ export interface IPublicResourceTypeConfig {
|
||||
description?: string;
|
||||
|
||||
/** 资源 icon 标识 */
|
||||
icon?: React.ReactElement;
|
||||
icon?: React.ReactElement | React.FunctionComponent | React.ComponentClass;
|
||||
|
||||
/**
|
||||
* 默认视图类型
|
||||
|
||||
@ -4,7 +4,7 @@ import { IPublicResourceTypeConfig } from './resource-type-config';
|
||||
export interface IPublicTypeResourceType {
|
||||
resourceName: string;
|
||||
|
||||
resourceType: 'editor' | 'webview';
|
||||
resourceType: 'editor' | 'webview' | string;
|
||||
|
||||
(ctx: IPublicModelPluginContext, options: Object): IPublicResourceTypeConfig;
|
||||
}
|
||||
@ -15,6 +15,11 @@ export interface IPublicTypeWidgetBaseConfig {
|
||||
props?: Record<string, any>;
|
||||
content?: any;
|
||||
contentProps?: Record<string, any>;
|
||||
|
||||
/**
|
||||
* 优先级,值越小,优先级越高,优先级高的会排在前面
|
||||
*/
|
||||
index?: number;
|
||||
}
|
||||
|
||||
export interface IPublicTypePanelDockConfig extends IPublicTypeWidgetBaseConfig {
|
||||
|
||||
@ -11,6 +11,7 @@ const jestConfig = {
|
||||
'!**/node_modules/**',
|
||||
'!**/vendor/**',
|
||||
],
|
||||
setupFilesAfterEnv: ['./jest.setup.js'],
|
||||
};
|
||||
|
||||
// 只对本仓库内的 pkg 做 mapping
|
||||
|
||||
1
packages/utils/jest.setup.js
Normal file
1
packages/utils/jest.setup.js
Normal file
@ -0,0 +1 @@
|
||||
import '@testing-library/jest-dom';
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-utils",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"description": "Utils for Ali lowCode engine",
|
||||
"files": [
|
||||
"lib",
|
||||
@ -9,20 +9,23 @@
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
"scripts": {
|
||||
"test": "build-scripts test --config build.test.json",
|
||||
"test": "build-scripts test --config build.test.json --jest-coverage",
|
||||
"build": "build-scripts build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alifd/next": "^1.19.16",
|
||||
"@alilc/lowcode-types": "1.2.2",
|
||||
"@alilc/lowcode-types": "1.2.3",
|
||||
"lodash": "^4.17.21",
|
||||
"mobx": "^6.3.0",
|
||||
"react": "^16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alib/build-scripts": "^0.1.18",
|
||||
"@testing-library/jest-dom": "^6.1.4",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@types/node": "^13.7.1",
|
||||
"@types/react": "^16"
|
||||
"@types/react": "^16",
|
||||
"react-dom": "^16.14.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { IPublicTypeActionContentObject } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isActionContentObject(obj: any): obj is IPublicTypeActionContentObject {
|
||||
return obj && typeof obj === 'object';
|
||||
return isObject(obj);
|
||||
}
|
||||
|
||||
@ -2,7 +2,9 @@ import { isValidElement } from 'react';
|
||||
import { isReactComponent } from '../is-react';
|
||||
import { IPublicTypeCustomView } from '@alilc/lowcode-types';
|
||||
|
||||
|
||||
export function isCustomView(obj: any): obj is IPublicTypeCustomView {
|
||||
return obj && (isValidElement(obj) || isReactComponent(obj));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return isValidElement(obj) || isReactComponent(obj);
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicEnumDragObjectType } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isDragAnyObject(obj: any): boolean {
|
||||
return obj && obj.type !== IPublicEnumDragObjectType.NodeData && obj.type !== IPublicEnumDragObjectType.Node;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type !== IPublicEnumDragObjectType.NodeData && obj.type !== IPublicEnumDragObjectType.Node;
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicEnumDragObjectType, IPublicTypeDragNodeDataObject } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isDragNodeDataObject(obj: any): obj is IPublicTypeDragNodeDataObject {
|
||||
return obj && obj.type === IPublicEnumDragObjectType.NodeData;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type === IPublicEnumDragObjectType.NodeData;
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicEnumDragObjectType, IPublicModelNode, IPublicTypeDragNodeObject } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isDragNodeObject<Node = IPublicModelNode>(obj: any): obj is IPublicTypeDragNodeObject<Node> {
|
||||
return obj && obj.type === IPublicEnumDragObjectType.Node;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type === IPublicEnumDragObjectType.Node;
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
import { isFunction } from '../is-function';
|
||||
import { isReactClass } from '../is-react';
|
||||
import { IPublicTypeDynamicSetter } from '@alilc/lowcode-types';
|
||||
|
||||
|
||||
export function isDynamicSetter(obj: any): obj is IPublicTypeDynamicSetter {
|
||||
return obj && typeof obj === 'function' && !isReactClass(obj);
|
||||
if (!isFunction(obj)) {
|
||||
return false;
|
||||
}
|
||||
return !isReactClass(obj);
|
||||
}
|
||||
|
||||
3
packages/utils/src/check-types/is-function.ts
Normal file
3
packages/utils/src/check-types/is-function.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function isFunction(obj: any): obj is Function {
|
||||
return obj && typeof obj === 'function';
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
|
||||
// type checks
|
||||
|
||||
import { IPublicTypeI18nData } from "@alilc/lowcode-types";
|
||||
import { IPublicTypeI18nData } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isI18nData(obj: any): obj is IPublicTypeI18nData {
|
||||
return obj && obj.type === 'i18n';
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type === 'i18n';
|
||||
}
|
||||
|
||||
@ -1,10 +1,26 @@
|
||||
import { IPublicTypeJSFunction } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
interface InnerJsFunction {
|
||||
type: 'JSExpression';
|
||||
source: string;
|
||||
value: string;
|
||||
extType: 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部版本 的 { type: 'JSExpression', source: '', value: '', extType: 'function' } 能力上等同于 JSFunction
|
||||
*/
|
||||
export function isInnerJsFunction(data: any) {
|
||||
return data && data.type === 'JSExpression' && data.extType === 'function';
|
||||
export function isInnerJsFunction(data: any): data is InnerJsFunction {
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSExpression' && data.extType === 'function';
|
||||
}
|
||||
|
||||
export function isJSFunction(data: any): boolean {
|
||||
return typeof data === 'object' && data && data.type === 'JSFunction' || isInnerJsFunction(data);
|
||||
export function isJSFunction(data: any): data is IPublicTypeJSFunction {
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSFunction' || isInnerJsFunction(data);
|
||||
}
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
import { IPublicTypeJSBlock } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isJSBlock(data: any): boolean {
|
||||
return data && data.type === 'JSBlock';
|
||||
export function isJSBlock(data: any): data is IPublicTypeJSBlock {
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSBlock';
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { IPublicTypeJSExpression } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
/**
|
||||
* 为了避免把 { type: 'JSExpression', extType: 'function' } 误判为表达式,故增加如下逻辑。
|
||||
@ -11,5 +12,8 @@ import { IPublicTypeJSExpression } from '@alilc/lowcode-types';
|
||||
* @returns
|
||||
*/
|
||||
export function isJSExpression(data: any): data is IPublicTypeJSExpression {
|
||||
return data && data.type === 'JSExpression' && data.extType !== 'function';
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSExpression' && data.extType !== 'function';
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeJSSlot } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isJSSlot(data: any): data is IPublicTypeJSSlot {
|
||||
return data && data.type === 'JSSlot';
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return data.type === 'JSSlot';
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeLocationChildrenDetail, IPublicTypeLocationDetailType } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isLocationChildrenDetail(obj: any): obj is IPublicTypeLocationChildrenDetail {
|
||||
return obj && obj.type === IPublicTypeLocationDetailType.Children;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return obj.type === IPublicTypeLocationDetailType.Children;
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeLocationData } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isLocationData(obj: any): obj is IPublicTypeLocationData {
|
||||
return obj && obj.target && obj.detail;
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return 'target' in obj && 'detail' in obj;
|
||||
}
|
||||
@ -1,6 +1,15 @@
|
||||
import { IPublicTypeComponentSchema, IPublicTypeProjectSchema } from "@alilc/lowcode-types";
|
||||
import { isComponentSchema } from "./is-component-schema";
|
||||
import { IPublicTypeComponentSchema, IPublicTypeProjectSchema } from '@alilc/lowcode-types';
|
||||
import { isComponentSchema } from './is-component-schema';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isLowcodeProjectSchema(data: any): data is IPublicTypeProjectSchema<IPublicTypeComponentSchema> {
|
||||
return data && data.componentsTree && data.componentsTree.length && isComponentSchema(data.componentsTree[0]);
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!('componentsTree' in data) || data.componentsTree.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isComponentSchema(data.componentsTree[0]);
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeNodeSchema } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isNodeSchema(data: any): data is IPublicTypeNodeSchema {
|
||||
return data && data.componentName && !data.isNode;
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return 'componentName' in data && !data.isNode;
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicModelNode } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isNode<Node = IPublicModelNode>(node: any): node is Node {
|
||||
return node && node.isNode;
|
||||
if (!isObject(node)) {
|
||||
return false;
|
||||
}
|
||||
return node.isNode;
|
||||
}
|
||||
3
packages/utils/src/check-types/is-object.ts
Normal file
3
packages/utils/src/check-types/is-object.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function isObject(obj: any): boolean {
|
||||
return obj && typeof obj === 'object';
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
import { IPublicTypeComponentMap, IPublicTypeProCodeComponent } from '@alilc/lowcode-types';
|
||||
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isProCodeComponentType(desc: IPublicTypeComponentMap): desc is IPublicTypeProCodeComponent {
|
||||
if (!isObject(desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 'package' in desc;
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { IPublicTypeProjectSchema } from "@alilc/lowcode-types";
|
||||
import { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isProjectSchema(data: any): data is IPublicTypeProjectSchema {
|
||||
return data && data.componentsTree;
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
return 'componentsTree' in data;
|
||||
}
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { IPublicTypeSetterConfig } from '@alilc/lowcode-types';
|
||||
import { isCustomView } from './is-custom-view';
|
||||
|
||||
import { isObject } from '../is-object';
|
||||
|
||||
export function isSetterConfig(obj: any): obj is IPublicTypeSetterConfig {
|
||||
return obj && typeof obj === 'object' && 'componentName' in obj && !isCustomView(obj);
|
||||
if (!isObject(obj)) {
|
||||
return false;
|
||||
}
|
||||
return 'componentName' in obj && !isCustomView(obj);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user