mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
refactor(editor): move worker renderer to presets with basic test (#10127)
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
import '../../style.css';
|
||||
|
||||
import { ViewportTurboRendererExtension } from '@blocksuite/affine-shared/viewport-renderer';
|
||||
import { effects as blocksEffects } from '@blocksuite/blocks/effects';
|
||||
import { AffineEditorContainer } from '@blocksuite/presets';
|
||||
import { effects as presetsEffects } from '@blocksuite/presets/effects';
|
||||
|
||||
import { createEmptyDoc } from '../../apps/_common/helper';
|
||||
|
||||
blocksEffects();
|
||||
presetsEffects();
|
||||
|
||||
export const { doc } = createEmptyDoc();
|
||||
export const editor = new AffineEditorContainer();
|
||||
|
||||
editor.edgelessSpecs = [
|
||||
...editor.edgelessSpecs,
|
||||
ViewportTurboRendererExtension,
|
||||
];
|
||||
|
||||
editor.doc = doc;
|
||||
editor.mode = 'edgeless';
|
||||
@@ -1,29 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Renderer Example</title>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: var(--affine-white-90);
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
#container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="module" src="./main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,10 +0,0 @@
|
||||
import { addSampleNotes } from './doc-generator.js';
|
||||
import { doc, editor } from './editor.js';
|
||||
|
||||
function main() {
|
||||
doc.load();
|
||||
addSampleNotes(6);
|
||||
}
|
||||
|
||||
main();
|
||||
document.querySelector('#container')?.append(editor);
|
||||
@@ -120,10 +120,6 @@ export default defineConfig(({ mode }) => {
|
||||
'examples/multiple-editors/edgeless-edgeless/index.html'
|
||||
),
|
||||
'examples/inline': resolve(__dirname, 'examples/inline/index.html'),
|
||||
'examples/renderer': resolve(
|
||||
__dirname,
|
||||
'examples/renderer/index.html'
|
||||
),
|
||||
},
|
||||
treeshake: true,
|
||||
output: {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"description": "Prebuilt BlockSuite editors and opt-in additional UI components.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc",
|
||||
"test:unit": "vitest --browser.headless --run",
|
||||
"test:debug": "PWDEBUG=1 npx vitest"
|
||||
@@ -46,6 +47,9 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@vanilla-extract/vite-plugin": "^5.0.0",
|
||||
"vite": "^6.1.0",
|
||||
"vite-plugin-istanbul": "^6.0.2",
|
||||
"vite-plugin-wasm": "^3.4.1",
|
||||
"vitest": "^3.0.0"
|
||||
},
|
||||
"version": "0.19.0"
|
||||
|
||||
21
blocksuite/presets/renderer.html
Normal file
21
blocksuite/presets/renderer.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Kalam&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Debug Entry</title>
|
||||
</head>
|
||||
<body>
|
||||
<script
|
||||
type="module"
|
||||
src="./src/__tests__/utils/renderer-entry.ts"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ViewportTurboRendererExtension } from '@blocksuite/affine-shared/viewport-renderer';
|
||||
import { beforeEach, describe, expect, test } from 'vitest';
|
||||
|
||||
import { wait } from '../utils/common.js';
|
||||
import { addSampleNotes } from '../utils/doc-generator.js';
|
||||
import { setupEditor } from '../utils/setup.js';
|
||||
|
||||
describe('viewport turbo renderer', () => {
|
||||
beforeEach(async () => {
|
||||
const cleanup = await setupEditor('edgeless', [
|
||||
ViewportTurboRendererExtension,
|
||||
]);
|
||||
return cleanup;
|
||||
});
|
||||
|
||||
test('should render 6 notes in viewport', async () => {
|
||||
addSampleNotes(doc, 6);
|
||||
await wait();
|
||||
|
||||
const notes = document.querySelectorAll('affine-edgeless-note');
|
||||
expect(notes.length).toBe(6);
|
||||
});
|
||||
});
|
||||
@@ -1,33 +1,32 @@
|
||||
import { Text } from '@blocksuite/store';
|
||||
import { type Store, Text } from '@blocksuite/store';
|
||||
|
||||
import { doc } from './editor.js';
|
||||
|
||||
function addParagraph(noteId: string, content: string) {
|
||||
function addParagraph(doc: Store, noteId: string, content: string) {
|
||||
const props = { text: new Text(content) };
|
||||
doc.addBlock('affine:paragraph', props, noteId);
|
||||
}
|
||||
|
||||
function addSampleNote(noteId: string, i: number) {
|
||||
addParagraph(noteId, `Note ${i + 1}`);
|
||||
addParagraph(noteId, 'Hello World!');
|
||||
function addSampleNote(doc: Store, noteId: string, i: number) {
|
||||
addParagraph(doc, noteId, `Note ${i + 1}`);
|
||||
addParagraph(doc, noteId, 'Hello World!');
|
||||
addParagraph(
|
||||
doc,
|
||||
noteId,
|
||||
'Hello World! Lorem ipsum dolor sit amet. Consectetur adipiscing elit. Sed do eiusmod tempor incididunt.'
|
||||
);
|
||||
addParagraph(
|
||||
doc,
|
||||
noteId,
|
||||
'你好这是测试,这是一个为了换行而写的中文段落。这个段落会自动换行。'
|
||||
);
|
||||
}
|
||||
|
||||
export function addSampleNotes(n: number) {
|
||||
export function addSampleNotes(doc: Store, n: number) {
|
||||
const cols = Math.ceil(Math.sqrt(n));
|
||||
const NOTE_WIDTH = 500;
|
||||
const NOTE_HEIGHT = 250;
|
||||
const SPACING = 50;
|
||||
|
||||
const rootId = doc.addBlock('affine:page', {});
|
||||
doc.addBlock('affine:surface', {}, rootId);
|
||||
const rootId = doc.getBlocksByFlavour('affine:page')[0]?.id;
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
const row = Math.floor(i / cols);
|
||||
@@ -37,6 +36,6 @@ export function addSampleNotes(n: number) {
|
||||
|
||||
const xywh = `[${x},${y},${NOTE_WIDTH},${NOTE_HEIGHT}]`;
|
||||
const noteId = doc.addBlock('affine:note', { xywh }, rootId);
|
||||
addSampleNote(noteId, i);
|
||||
addSampleNote(doc, noteId, i);
|
||||
}
|
||||
}
|
||||
12
blocksuite/presets/src/__tests__/utils/renderer-entry.ts
Normal file
12
blocksuite/presets/src/__tests__/utils/renderer-entry.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ViewportTurboRendererExtension } from '@blocksuite/affine-shared/viewport-renderer';
|
||||
|
||||
import { addSampleNotes } from './doc-generator.js';
|
||||
import { setupEditor } from './setup.js';
|
||||
|
||||
async function init() {
|
||||
setupEditor('edgeless', [ViewportTurboRendererExtension]);
|
||||
addSampleNotes(doc, 6);
|
||||
doc.load();
|
||||
}
|
||||
|
||||
init();
|
||||
@@ -2,7 +2,7 @@ import '@toeverything/theme/style.css';
|
||||
import '@toeverything/theme/fonts.css';
|
||||
|
||||
import { effects as blocksEffects } from '@blocksuite/blocks/effects';
|
||||
import type { Store, Transformer } from '@blocksuite/store';
|
||||
import type { ExtensionType, Store, Transformer } from '@blocksuite/store';
|
||||
|
||||
import { effects } from '../../effects.js';
|
||||
|
||||
@@ -59,7 +59,11 @@ function initCollection(collection: TestWorkspace) {
|
||||
doc.resetHistory();
|
||||
}
|
||||
|
||||
async function createEditor(collection: TestWorkspace, mode: DocMode = 'page') {
|
||||
async function createEditor(
|
||||
collection: TestWorkspace,
|
||||
mode: DocMode = 'page',
|
||||
extensions: ExtensionType[] = []
|
||||
) {
|
||||
const app = document.createElement('div');
|
||||
const blockCollection = collection.docs.values().next().value;
|
||||
assertExists(blockCollection, 'Need to create a doc first');
|
||||
@@ -69,9 +73,11 @@ async function createEditor(collection: TestWorkspace, mode: DocMode = 'page') {
|
||||
editor.mode = mode;
|
||||
editor.pageSpecs = editor.pageSpecs.concat([
|
||||
FontConfigExtension(CommunityCanvasTextFonts),
|
||||
...extensions,
|
||||
]);
|
||||
editor.edgelessSpecs = editor.edgelessSpecs.concat([
|
||||
FontConfigExtension(CommunityCanvasTextFonts),
|
||||
...extensions,
|
||||
]);
|
||||
app.append(editor);
|
||||
|
||||
@@ -87,7 +93,10 @@ async function createEditor(collection: TestWorkspace, mode: DocMode = 'page') {
|
||||
return app;
|
||||
}
|
||||
|
||||
export async function setupEditor(mode: DocMode = 'page') {
|
||||
export async function setupEditor(
|
||||
mode: DocMode = 'page',
|
||||
extensions: ExtensionType[] = []
|
||||
) {
|
||||
const collection = new TestWorkspace(createCollectionOptions());
|
||||
collection.storeExtensions = StoreExtensions;
|
||||
collection.meta.initialize();
|
||||
@@ -95,7 +104,7 @@ export async function setupEditor(mode: DocMode = 'page') {
|
||||
window.collection = collection;
|
||||
|
||||
initCollection(collection);
|
||||
const appElement = await createEditor(collection, mode);
|
||||
const appElement = await createEditor(collection, mode, extensions);
|
||||
|
||||
return () => {
|
||||
appElement.remove();
|
||||
|
||||
36
blocksuite/presets/vite.config.ts
Normal file
36
blocksuite/presets/vite.config.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { cpus } from 'node:os';
|
||||
|
||||
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';
|
||||
import { defineConfig } from 'vite';
|
||||
import wasm from 'vite-plugin-wasm';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(() => {
|
||||
return {
|
||||
plugins: [wasm(), vanillaExtractPlugin()],
|
||||
esbuild: {
|
||||
target: 'es2022',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
},
|
||||
build: {
|
||||
target: 'es2022',
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
cache: false,
|
||||
maxParallelFileOps: Math.max(1, cpus().length - 1),
|
||||
onwarn(warning, defaultHandler) {
|
||||
if (
|
||||
warning.code &&
|
||||
['EVAL', 'SOURCEMAP_ERROR'].includes(warning.code)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
defaultHandler(warning);
|
||||
},
|
||||
treeshake: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user