Skip to content

Commit

Permalink
refactor(facade): separated to plugins to be composable (#3730)
Browse files Browse the repository at this point in the history
Co-authored-by: 白熱 <sonne@asaki.me>
Co-authored-by: lumixraku <lumixraku@gmail.com>
  • Loading branch information
3 people authored Oct 30, 2024
1 parent 31e58f0 commit bc6a7bb
Show file tree
Hide file tree
Showing 329 changed files with 5,888 additions and 3,830 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pnpm dev

### Architecture

Please refer to the [architecture doc](https://github.com/dream-num/univer/wiki/Univer-Architecture).
Please refer to [Architecture](https://univer.ai/guides/sheet/architecture/univer), and also [ISOMORPHIC.md](./docs/ISOMORPHIC.md) for more guidance on how to set up plugins.

### Source code organization

Expand Down
10 changes: 6 additions & 4 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@
## 🌈 亮点

- 📈 **支持多种类文档** Univer 目前支持**电子表格****富文本文档**,未来还会增加对**幻灯片**的支持。
- 🧙‍♀️ **多端同构** 可以在浏览器和 Node.js 环境中运行。
- ⚙️ **易于集成** Univer 能够无缝集成到你的应用当中。
- 🎇 **功能强大** Univer 支持非常多的功能,包括但不限于**公式计算****条件格式****数据验证****筛选****协同编辑****打印****导入导出**等等,更多的功能即将陆续发布。
- 🔌 **高度可扩展**Univer 的 *插件化架构**Facade API* 使得扩展 Univer 的功能变得轻松容易,你可以在 Univer 之上实现自己的业务需求。
- 🔌 **高度可扩展** Univer 的*插件化架构*使得扩展 Univer 的功能变得轻松容易,你可以在 Univer 之上实现自己的业务需求。
- 💄 **高度可定制** 你可以通过*主题*来自定义 Univer 的外观,另外还支持国际化。
- 🥤 **易于使用** *Presets**Facade API* 使得 Univer 很容易上手
-**性能优越**
- ✏️ Univer 实现了基于 canvas 的 *渲染引擎*,能够高效地渲染不同类型的文档。渲染引擎支持 *标点挤压* *盘古之白* *图文混排* *滚动贴图* 等高级特性。
- ✏️ Univer 实现了基于 canvas 的*渲染引擎*,能够高效地渲染不同类型的文档。渲染引擎支持 *标点挤压* *盘古之白* *图文混排* *滚动贴图* 等高级特性。
- 🧮 自研的 *公式引擎* 拥有超快的计算速度,还能在 Web Worker 中运行,未来将会支持服务端计算。
- 🌌 **高度集成** 文档、电子表格和幻灯片能够互操作,甚至是渲染在同一个画布上,使得信息和数据能够在 Univer 当中自由地流动。

Expand All @@ -76,12 +78,12 @@ Univer 提供了丰富的电子表格、文档和幻灯片功能。以下是一
- **评论**:允许向单元格添加评论以提供额外信息。
- **十字高亮**:支持在电子表格中显示十字高亮,以帮助用户快速定位选中的单元格。
- **数据透视表**[^1]:支持数据透视表,允许用户对数据进行汇总和分析。
- **协同编辑**[^1]:支持多个用户同时编辑电子表格。
- **协同编辑**[^1]:支持多个用户同时编辑电子表格,同时支持历史记录与恢复
- **打印**[^1]:允许打印电子表格或将其导出为 PDF。
- **导入和导出**[^1]:支持导入导出 XLSX 格式的数据。
- **图表**[^2]:由 [VChart][vchart-link] 支持第三方图表。

### 📝 Univer Doc(积极开发中
### 📝 Univer Doc(beta 测试中

- **核心功能**:Univer 支持文档的核心功能,包括段落、标题、列表、上标、下标等。
- **列表**:支持有序列表、无序列表和任务列表。
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ Extensible. High-performance. Embedded to your application.
## 🌈 Highlights

- 📈 Univer is designed to support **spreadsheets**, **documents** and **presentation**.
- 🧙‍♀️ Univer is **isomorphic**. It can run both on browsers and Node.js (in the future, mobile devices as well), with the same API.
- ⚙️ Univer is easily **embeddable**, allowing seamless integration into your applications.
- 🎇 Univer is **powerful**, offering a wide range of features including **formulas**, **conditional formatting**, **data validation**, **filtering**, **collaborative editing**, **printing**, **import & export** and more features on the horizon.
- 🔌 Univer is **highly extensible**, thanks to its *plug-in architecture* and *Facade API* that makes it a delight for developers to implement their unique requirements on the top of Univer.
- 🔌 Univer is **highly extensible**, thanks to its *plug-in architecture* that makes it a delight for developers to implement their unique requirements on the top of Univer.
- 💄 Univer is **highly customizable**, allowing you to personalize its appearance using *themes*. It also provides support for internationalization (i18n).
- 🥤 Univer is **easy to work with**. The *Presets* & *Facade API* make it easy to hands on.
- ⚡ Univer in **performant**.
- ✏️ Univer boasts an efficient *rendering engine* based on canvas, capable of rendering various document types flawlessly. The rendering engines supports advanced typesetting features such as *punctuation squeezing*, *text and image layout* and *scroll buffering*.
- 🧮 Univer incorporates a lightning-fast *formula engine* that can operate in Web Workers or even on the server side.
Expand All @@ -76,12 +78,12 @@ Univer provides a wide range of features for spreadsheets, documents and present
- **Comments**: Enables adding comments to cells to provide additional information.
- **Cross-highlighting**: Supports displaying cross-highlighting in spreadsheets to help users quickly locate selected cells.
- **Pivot Tables**[^1]: Supports pivot tables, allowing users to summarize and analyze data.
- **Collaborative Editing**[^1]: Supports multiple users editing a spreadsheet simultaneously.
- **Collaborative Editing**[^1]: Supports multiple users editing a spreadsheet simultaneously. File history and recovering are also provided.
- **Printing**[^1]: Allows printing a spreadsheet or exporting it to PDF.
- **Import & Export**[^1]: Support for importing and exporting data in XLSX.
- **Charts**[^2]: Third-party chart support via [VChart][vchart-link].

### 📝 Univer Doc (Under Development)
### 📝 Univer Doc (beta)

- **Core Features**: Univer supports core document features, including paragraphs, headings, lists, superscript, subscript, and more.
- **Lists**: Supports ordered lists, unordered lists, and task lists.
Expand All @@ -107,7 +109,7 @@ Univer supports multiple languages, including:
- `vi-VN`
- `fa-IR`

`zh-CN` and `en-US` are officially supported, while the others are contributed by the community.
`zh-CN` and `en-US` are officially supported, while the others are contributed and maintained by the community.

You can add the language you want by [Using Custom Locales](https://univer.ai/guides/sheet/getting-started/i18n#using-custom-locales). You can also help us add new language support by referring to the [contribution guide](./CONTRIBUTING.md).

Expand All @@ -133,6 +135,11 @@ You can find all the examples in the [Univer Examples](https://univer.ai/example
Univer has a rich ecosystem that includes a wide range of tools and resources to help you get started with Univer: -->

## 🔗 Links

- [Official Site](https://univer.ai)
- [Presets Repository](https://github.com/dream-num/univer-presets)

## 💬 Community

[![][github-community-badge]][github-community-link] [![][discord-community-badge]][discord-community-link] [![][stackoverflow-community-badge]][stackoverflow-community-link]
Expand Down
1 change: 1 addition & 0 deletions common/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"javascript-obfuscator": "^4.1.1",
"vite": "^5.4.8",
"vite-plugin-dts": "^4.2.3",
"vite-plugin-external": "^4.3.1",
"vitest": "^2.1.2"
}
}
4 changes: 4 additions & 0 deletions common/shared/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const process = require('node:process');

const react = require('@vitejs/plugin-react');
const { default: dts } = require('vite-plugin-dts');
const vitePluginExternal = require('vite-plugin-external');
const { defineConfig, mergeConfig } = require('vitest/config');
const { autoExternalizeDependency } = require('./auto-externalize-dependency-plugin');
const { buildPkg } = require('./build-pkg');
Expand Down Expand Up @@ -61,6 +62,9 @@ function createViteConfig(overrideConfig, /** @type {IOptions} */ options) {
},
plugins: [
autoExternalizeDependency(),
vitePluginExternal({
nodeBuiltins: true, // exclude Node.js builtins from bundling
}),
dts({
entryRoot: 'src',
outDir: 'lib/types',
Expand Down
34 changes: 34 additions & 0 deletions docs/ISOMOPHIC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Building Isomorphic Univer

Univer is an isomorphic (full-stack) framework for building productivity tools, which means **support of Node.js is
at the same priority as browsers**.

To make your code aligned with the isomorphic architecture, please pay
attention to the following points:

## Separate Plugins

If the feature your are developing both needs to run on the server and the client, you should separate the feature into
at least two plugins. One for the underlying logic and the other for the UI.

The underlying logic often includes: models, commands and mutations to modify the data, and services to manage the data.

The UI includes menus, shortcuts, React components, Canvas elements, or other modules that depend on the browser environment.

For example, the filter feature is split into two plugins: `sheets-filter` and `sheets-filter-ui`.

Some modules rely on Node.js-only API such as `fs`, `path`, `child_process`, etc. These modules should be
implemented in another server-only plugin.

## Separate Facade API

**The Facade API is designed to be used by both the server and the client**. It should be implemented in each plugins and
composed by users (or the `@univerjs/presets` package) to provide a unified
API for the SDK.

You should implement the Facade API that can run on Node.js and the browser in the underlying logic plugins.

## Consider Implementing Commands in the Underlying Logic

Commands and especially those of type `MUTATION` should be implemented in the underlying logic plugins, and should not
read UI status directly to ensure that they can run on both Node.js and browsers.
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ test('diff default sheet toolbar', async () => {
const page = await context.newPage();
await page.goto('http://localhost:3000/sheets/');
await page.waitForTimeout(2000);

await page.evaluate(() => window.E2EControllerAPI.loadDefaultSheet());
await page.waitForTimeout(2000);
await page.waitForTimeout(8000);

const filename = generateSnapshotName('default-sheet-fullpage');
const screenshot = await page.screenshot({
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion examples-node/esbuild.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ const ctx = await esbuild[args.watch ? 'context' : 'build']({
bundle: true,
color: true,
sourcemap: args.watch,
minify: true,
minify: false,
target: 'chrome70',
entryPoints: [
'./src/cases/basic.ts',
'./src/sdk/worker.ts',
],
platform: 'node',
outdir: './dist',
define,
});
Expand Down
31 changes: 26 additions & 5 deletions examples-node/src/cases/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,33 @@
* limitations under the License.
*/

import type { IWorkbookData, Workbook } from '@univerjs/core';
import { UniverInstanceType } from '@univerjs/core';
import process from 'node:process';
import { awaitTime, FUniver } from '@univerjs/core';
import { createUniverOnNode } from '../sdk';

const univer = createUniverOnNode();
import '../sdk/facade';

univer.createUnit<IWorkbookData, Workbook>(UniverInstanceType.UNIVER_SHEET, {});
// From now on, Univer is a full-stack SDK.

// TODO: Facade API here
async function run(): Promise<void> {
const API = FUniver.newAPI(createUniverOnNode());
const univerSheet = API.createUniverSheet({});

const a1 = univerSheet.getActiveSheet().getRange('A1');
await a1.setValue({ v: 123 });

const b1 = univerSheet.getActiveSheet().getRange('B1');
await b1.setValue({ f: '=SUM(A1) * 6' });

await awaitTime(500);

// eslint-disable-next-line no-console
console.log('Debug, formula value', b1.getCellData()?.v);

// eslint-disable-next-line no-console
console.log(univerSheet.save());

process.exit(0);
}

run();
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@
* limitations under the License.
*/

import type { Nullable } from '@univerjs/core';
import type { SheetHyperLinkType } from '@univerjs/sheets-hyper-link';
import type { ISheetUrlParams } from './i-sheet-url-params';
// Facade API here are part of packages/facade/src/apis/everything.ts
// However some plugins are implemented incorrectly, so they are not included here.

export interface ISheetHyperLinkInfo {
type: SheetHyperLinkType;
name: string;
url: string;
searchObj: Nullable<ISheetUrlParams>;
handler: () => void;
}
import '@univerjs/sheets/facade';
import '@univerjs/sheets-data-validation/facade';
import '@univerjs/engine-formula/facade';
import '@univerjs/sheets-filter/facade';
import '@univerjs/sheets-formula/facade';
28 changes: 6 additions & 22 deletions examples-node/src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
* limitations under the License.
*/

import type { IMessageProtocol } from '@univerjs/rpc';
import type { Serializable } from 'node:child_process';
import { fork } from 'node:child_process';
import path from 'node:path';
import { Univer } from '@univerjs/core';
import { UniverDataValidationPlugin } from '@univerjs/data-validation';
Expand All @@ -30,16 +27,16 @@ import { UniverSheetsConditionalFormattingPlugin } from '@univerjs/sheets-condit
import { UniverSheetsDataValidationPlugin } from '@univerjs/sheets-data-validation';
import { UniverSheetsDrawingPlugin } from '@univerjs/sheets-drawing';
import { UniverSheetsFilterPlugin } from '@univerjs/sheets-filter';
import { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula';
import { UniverSheetsHyperLinkPlugin } from '@univerjs/sheets-hyper-link';
import { UniverSheetsSortPlugin } from '@univerjs/sheets-sort';
import { UniverThreadCommentPlugin } from '@univerjs/thread-comment';
import { Observable, shareReplay } from 'rxjs';

export function createUniverOnNode(): Univer {
const univer = new Univer();

registerBasicPlugins(univer);
reigsterSharedPlugins(univer);
registerSharedPlugins(univer);
registerRPCPlugin(univer);

registerDocPlugins(univer);
Expand All @@ -52,7 +49,7 @@ function registerBasicPlugins(univer: Univer): void {
univer.registerPlugin(UniverFormulaEnginePlugin, { notExecuteFormula: true });
}

function reigsterSharedPlugins(univer: Univer): void {
function registerSharedPlugins(univer: Univer): void {
univer.registerPlugin(UniverThreadCommentPlugin);
univer.registerPlugin(UniverDrawingPlugin);
}
Expand All @@ -64,6 +61,7 @@ function registerDocPlugins(univer: Univer): void {

function registerSheetPlugins(univer: Univer): void {
univer.registerPlugin(UniverSheetsPlugin);
univer.registerPlugin(UniverSheetsFormulaPlugin);
univer.registerPlugin(UniverSheetsConditionalFormattingPlugin);
univer.registerPlugin(UniverDataValidationPlugin);
univer.registerPlugin(UniverSheetsDataValidationPlugin);
Expand All @@ -74,20 +72,6 @@ function registerSheetPlugins(univer: Univer): void {
}

function registerRPCPlugin(univer: Univer): void {
const childFork = fork(path.join(__dirname, './worker.js'));
const messageProtocol: IMessageProtocol = {
send(message: unknown): void {
childFork.send(message as Serializable);
},
onMessage: new Observable<any>((subscriber) => {
const handler = (message: unknown) => {
subscriber.next(message);
};

childFork.on('message', handler);
return () => childFork.off('message', handler);
}).pipe(shareReplay(1)),
};

univer.registerPlugin(UniverRPCNodeMainPlugin, { messageProtocol });
const childPath = path.join(__dirname, '../sdk/worker.js');
univer.registerPlugin(UniverRPCNodeMainPlugin, { workerSrc: childPath });
}
4 changes: 2 additions & 2 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"@univerjs/drawing-ui": "workspace:*",
"@univerjs/engine-formula": "workspace:*",
"@univerjs/engine-render": "workspace:*",
"@univerjs/facade": "workspace:*",
"@univerjs/find-replace": "workspace:*",
"@univerjs/icons": "^0.1.84",
"@univerjs/mockdata": "workspace:*",
Expand All @@ -49,10 +48,11 @@
"@univerjs/sheets-hyper-link": "workspace:*",
"@univerjs/sheets-hyper-link-ui": "workspace:*",
"@univerjs/sheets-numfmt": "workspace:*",
"@univerjs/sheets-numfmt-ui": "workspace:*",
"@univerjs/sheets-sort": "workspace:*",
"@univerjs/sheets-sort-ui": "workspace:*",
"@univerjs/sheets-thread-comment": "workspace:*",
"@univerjs/sheets-thread-comment-base": "workspace:*",
"@univerjs/sheets-thread-comment-ui": "workspace:*",
"@univerjs/sheets-ui": "workspace:*",
"@univerjs/sheets-zen-editor": "workspace:*",
"@univerjs/slides": "workspace:*",
Expand Down
3 changes: 1 addition & 2 deletions examples/src/docs/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { LocaleType, LogLevel, Univer, UniverInstanceType, UserManagerService } from '@univerjs/core';
import { FUniver, LocaleType, LogLevel, Univer, UniverInstanceType, UserManagerService } from '@univerjs/core';
import { UniverDebuggerPlugin } from '@univerjs/debugger';
import { defaultTheme } from '@univerjs/design';
import { UniverDocsPlugin } from '@univerjs/docs';
Expand All @@ -25,7 +25,6 @@ import { UniverDocsThreadCommentUIPlugin } from '@univerjs/docs-thread-comment-u
import { UniverDocsUIPlugin } from '@univerjs/docs-ui';
import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula';
import { UniverRenderEnginePlugin } from '@univerjs/engine-render';
import { FUniver } from '@univerjs/facade';
import { DEFAULT_DOCUMENT_DATA_CN } from '@univerjs/mockdata';
import { UniverUIPlugin } from '@univerjs/ui';
import { enUS, faIR, ruRU, zhCN } from '../locales';
Expand Down
2 changes: 1 addition & 1 deletion examples/src/mobile-s/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { FUniver } from '@univerjs/facade';
import type { FUniver } from '@univerjs/core';
import type { IUniverRPCMainThreadConfig } from '@univerjs/rpc';
import { LocaleType, LogLevel, Univer, UniverInstanceType, UserManagerService } from '@univerjs/core';
import { defaultTheme } from '@univerjs/design';
Expand Down
2 changes: 2 additions & 0 deletions examples/src/sheets-multi/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { DEFAULT_WORKBOOK_DATA_DEMO } from '@univerjs/mockdata';
import { UniverSheetsPlugin } from '@univerjs/sheets';
import { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula';
import { UniverSheetsNumfmtPlugin } from '@univerjs/sheets-numfmt';
import { UniverSheetsNumfmtUIPlugin } from '@univerjs/sheets-numfmt-ui';
import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui';
import { UniverUIPlugin } from '@univerjs/ui';
import React, { useEffect } from 'react';
Expand Down Expand Up @@ -63,6 +64,7 @@ function factory(id: string) {

// sheet feature plugins
univer.registerPlugin(UniverSheetsNumfmtPlugin);
univer.registerPlugin(UniverSheetsNumfmtUIPlugin);
univer.registerPlugin(UniverSheetsFormulaPlugin);

// create univer sheet instance
Expand Down
2 changes: 2 additions & 0 deletions examples/src/sheets-uniscript/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { UNISCRIT_WORKBOOK_DATA_DEMO } from '@univerjs/mockdata';
import { UniverSheetsPlugin } from '@univerjs/sheets';
import { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula';
import { UniverSheetsNumfmtPlugin } from '@univerjs/sheets-numfmt';
import { UniverSheetsNumfmtUIPlugin } from '@univerjs/sheets-numfmt-ui';
import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui';
import { UniverUIPlugin } from '@univerjs/ui';
import { UniverUniscriptPlugin } from '@univerjs/uniscript';
Expand Down Expand Up @@ -59,6 +60,7 @@ univer.registerPlugin(UniverSheetsUIPlugin);

// sheet feature plugins
univer.registerPlugin(UniverSheetsNumfmtPlugin);
univer.registerPlugin(UniverSheetsNumfmtUIPlugin);
univer.registerPlugin(UniverDebuggerPlugin);
univer.registerPlugin(UniverFormulaEnginePlugin);
univer.registerPlugin(UniverSheetsFormulaPlugin);
Expand Down
Loading

0 comments on commit bc6a7bb

Please sign in to comment.