refactor(editor): remove default entry (#9600)

This commit is contained in:
Yifeng Wang
2025-01-09 14:01:48 +08:00
committed by GitHub
parent 422bac6cbe
commit cac0b7fd66
9 changed files with 13 additions and 384 deletions
@@ -1,26 +0,0 @@
import '../../style.css';
import { effects as blocksEffects } from '@blocksuite/blocks/effects';
import { effects as presetsEffects } from '@blocksuite/presets/effects';
import { setupEdgelessTemplate } from '../_common/setup.js';
import {
createDefaultDocCollection,
initDefaultDocCollection,
} from './utils/collection.js';
import { mountDefaultDocEditor } from './utils/editor.js';
blocksEffects();
presetsEffects();
async function main() {
if (window.collection) return;
setupEdgelessTemplate();
const collection = await createDefaultDocCollection();
await initDefaultDocCollection(collection);
await mountDefaultDocEditor(collection);
}
main().catch(console.error);
@@ -1,14 +0,0 @@
import {
EdgelessEditorBlockSpecs,
PageEditorBlockSpecs,
} from '@blocksuite/blocks';
export function getExampleSpecs() {
const pageModeSpecs = PageEditorBlockSpecs;
const edgelessModeSpecs = EdgelessEditorBlockSpecs;
return {
pageModeSpecs,
edgelessModeSpecs,
};
}
@@ -1,115 +0,0 @@
import { AffineSchemas } from '@blocksuite/blocks';
import type { BlockSuiteFlags } from '@blocksuite/global/types';
import { Job, nanoid, Schema, Text } from '@blocksuite/store';
import {
type DocCollectionOptions,
TestWorkspace,
} from '@blocksuite/store/test';
import {
BroadcastChannelAwarenessSource,
BroadcastChannelDocSource,
IndexedDBBlobSource,
IndexedDBDocSource,
} from '@blocksuite/sync';
import * as Y from 'yjs';
import { WebSocketAwarenessSource } from '../../_common/sync/websocket/awareness';
import { WebSocketDocSource } from '../../_common/sync/websocket/doc';
const BASE_WEBSOCKET_URL = new URL(import.meta.env.PLAYGROUND_WS);
export async function createDefaultDocCollection() {
const idGenerator = nanoid;
const schema = new Schema();
schema.register(AffineSchemas);
const params = new URLSearchParams(location.search);
let docSources: DocCollectionOptions['docSources'] = {
main: new IndexedDBDocSource(),
};
let awarenessSources: DocCollectionOptions['awarenessSources'];
const room = params.get('room');
if (room) {
const ws = new WebSocket(new URL(`/room/${room}`, BASE_WEBSOCKET_URL));
await new Promise((resolve, reject) => {
ws.addEventListener('open', resolve);
ws.addEventListener('error', reject);
})
.then(() => {
docSources = {
main: new IndexedDBDocSource(),
shadows: [new WebSocketDocSource(ws)],
};
awarenessSources = [new WebSocketAwarenessSource(ws)];
})
.catch(() => {
docSources = {
main: new IndexedDBDocSource(),
shadows: [new BroadcastChannelDocSource()],
};
awarenessSources = [
new BroadcastChannelAwarenessSource('collabPlayground'),
];
});
}
const flags: Partial<BlockSuiteFlags> = Object.fromEntries(
[...params.entries()]
.filter(([key]) => key.startsWith('enable_'))
.map(([k, v]) => [k, v === 'true'])
);
const options: DocCollectionOptions = {
id: 'collabPlayground',
schema,
idGenerator,
blobSources: {
main: new IndexedDBBlobSource('collabPlayground'),
},
docSources,
awarenessSources,
defaultFlags: {
enable_synced_doc_block: true,
enable_pie_menu: true,
enable_lasso_tool: true,
enable_color_picker: true,
...flags,
},
};
const collection = new TestWorkspace(options);
collection.start();
// debug info
window.collection = collection;
window.blockSchemas = AffineSchemas;
window.job = new Job({
schema: collection.schema,
blobCRUD: collection.blobSync,
docCRUD: {
create: (id: string) => collection.createDoc({ id }),
get: (id: string) => collection.getDoc(id),
delete: (id: string) => collection.removeDoc(id),
},
});
window.Y = Y;
return collection;
}
export async function initDefaultDocCollection(collection: TestWorkspace) {
const params = new URLSearchParams(location.search);
await collection.waitForSynced();
const shouldInit = collection.docs.size === 0 && !params.get('room');
if (shouldInit) {
collection.meta.initialize();
const doc = collection.createDoc({ id: 'doc:home' });
doc.load();
const rootId = doc.addBlock('affine:page', {
title: new Text(),
});
doc.addBlock('affine:surface', {}, rootId);
doc.resetHistory();
}
}
@@ -1,135 +0,0 @@
import type { EditorHost } from '@blocksuite/block-std';
import {
CommunityCanvasTextFonts,
DocModeExtension,
DocModeProvider,
EditorSettingExtension,
FontConfigExtension,
GenerateDocUrlExtension,
GenerateDocUrlProvider,
NotificationExtension,
OverrideThemeExtension,
ParseDocUrlExtension,
RefNodeSlotsProvider,
SpecProvider,
} from '@blocksuite/blocks';
import { AffineEditorContainer } from '@blocksuite/presets';
import type { ExtensionType, Workspace } from '@blocksuite/store';
import { AttachmentViewerPanel } from '../../_common/components/attachment-viewer-panel.js';
import { CollabDebugMenu } from '../../_common/components/collab-debug-menu.js';
import { DocsPanel } from '../../_common/components/docs-panel.js';
import { LeftSidePanel } from '../../_common/components/left-side-panel.js';
import {
getDocFromUrlParams,
listenHashChange,
setDocModeFromUrlParams,
} from '../../_common/history.js';
import {
mockDocModeService,
mockEditorSetting,
mockGenerateDocUrlService,
mockNotificationService,
mockParseDocUrlService,
mockPeekViewExtension,
themeExtension,
} from '../../_common/mock-services.js';
import { getExampleSpecs } from '../specs-examples/index.js';
export async function mountDefaultDocEditor(collection: Workspace) {
const app = document.getElementById('app');
if (!app) return;
const url = new URL(location.toString());
const doc = getDocFromUrlParams(collection, url);
const attachmentViewerPanel = new AttachmentViewerPanel();
const editor = new AffineEditorContainer();
const specs = getExampleSpecs();
editor.pageSpecs = patchPageRootSpec([...specs.pageModeSpecs]);
editor.edgelessSpecs = patchPageRootSpec([...specs.edgelessModeSpecs]);
SpecProvider.getInstance().extendSpec('edgeless:preview', [
OverrideThemeExtension(themeExtension),
]);
editor.doc = doc;
editor.mode = 'page';
editor.std
.get(RefNodeSlotsProvider)
.docLinkClicked.on(({ pageId: docId }) => {
const target = collection.getDoc(docId);
if (!target) {
throw new Error(`Failed to jump to doc ${docId}`);
}
const url = editor.std
.get(GenerateDocUrlProvider)
.generateDocUrl(target.id);
if (url) history.pushState({}, '', url);
target.load();
editor.doc = target;
});
app.append(editor);
await editor.updateComplete;
const modeService = editor.host!.std.get(DocModeProvider);
editor.mode = modeService.getPrimaryMode(doc.id);
setDocModeFromUrlParams(modeService, url.searchParams, doc.id);
editor.slots.docUpdated.on(({ newDocId }) => {
editor.mode = modeService.getPrimaryMode(newDocId);
});
const leftSidePanel = new LeftSidePanel();
const docsPanel = new DocsPanel();
docsPanel.editor = editor;
const collabDebugMenu = new CollabDebugMenu();
collabDebugMenu.collection = collection;
collabDebugMenu.editor = editor;
collabDebugMenu.leftSidePanel = leftSidePanel;
collabDebugMenu.docsPanel = docsPanel;
document.body.append(attachmentViewerPanel);
document.body.append(leftSidePanel);
document.body.append(collabDebugMenu);
// debug info
window.editor = editor;
window.doc = doc;
Object.defineProperty(globalThis, 'host', {
get() {
return document.querySelector<EditorHost>('editor-host');
},
});
Object.defineProperty(globalThis, 'std', {
get() {
return document.querySelector<EditorHost>('editor-host')?.std;
},
});
listenHashChange(collection, editor, docsPanel);
return editor;
function patchPageRootSpec(spec: ExtensionType[]) {
const setEditorModeCallBack = editor.switchEditor.bind(editor);
const getEditorModeCallback = () => editor.mode;
const newSpec: typeof spec = [
...spec,
DocModeExtension(
mockDocModeService(getEditorModeCallback, setEditorModeCallBack)
),
OverrideThemeExtension(themeExtension),
ParseDocUrlExtension(mockParseDocUrlService(collection)),
GenerateDocUrlExtension(mockGenerateDocUrlService(collection)),
NotificationExtension(mockNotificationService(editor)),
FontConfigExtension(CommunityCanvasTextFonts),
mockPeekViewExtension(attachmentViewerPanel),
EditorSettingExtension(mockEditorSetting()),
];
return newSpec;
}
}
@@ -1,26 +0,0 @@
function escapeHtml(html: string) {
const div = document.createElement('div');
div.textContent = html;
return div.innerHTML;
}
// Custom function to emit toast notifications
export function notify(
message: string,
variant: 'primary' | 'success' | 'neutral' | 'warning' | 'danger' = 'primary',
icon = 'info-circle',
duration = 2000
) {
const alert = Object.assign(document.createElement('sl-alert'), {
variant,
closable: true,
duration: duration,
innerHTML: `
<sl-icon name="${icon}" slot="icon"></sl-icon>
${escapeHtml(message)}
`,
});
document.body.append(alert);
return alert.toast();
}
+12 -10
View File
@@ -5,15 +5,11 @@
<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 />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://fonts.googleapis.com/css2?family=Kalam&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&display=swap"
rel="stylesheet"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BlockSuite Playground</title>
<style>
html,
@@ -34,6 +30,15 @@
margin-top: 78px;
}
:root .tp-dfwv {
position: fixed;
overflow: scroll;
top: 0;
bottom: 0;
right: 0;
}
@media print {
doc-title {
margin-top: 0px;
@@ -43,11 +48,8 @@
</head>
<body>
<script type="module" src="./apps/default/main.ts"></script>
<div
id="app"
style="margin: 0; overflow: initial; height: 100%; box-shadow: initial"
>
<script type="module" src="./apps/starter/main.ts"></script>
<div id="app">
<div id="inspector"></div>
</div>
</body>
-56
View File
@@ -1,56 +0,0 @@
<!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>BlockSuite Playground</title>
<style>
html,
body {
height: 100%;
overflow: hidden;
margin: 0;
padding: 0;
background-color: var(--affine-white-90);
transition: background-color 0.3s;
}
* {
box-sizing: border-box;
}
doc-title {
margin-top: 78px;
}
:root .tp-dfwv {
position: fixed;
overflow: scroll;
top: 0;
bottom: 0;
right: 0;
}
@media print {
doc-title {
margin-top: 0px;
}
}
</style>
</head>
<body>
<script type="module" src="../apps/starter/main.ts"></script>
<div id="app">
<div id="inspector"></div>
</div>
</body>
</html>
-1
View File
@@ -213,7 +213,6 @@ export default defineConfig(({ mode }) => {
},
input: {
main: resolve(__dirname, 'index.html'),
'starter/': resolve(__dirname, 'starter/index.html'),
'examples/basic/page': resolve(
__dirname,
'examples/basic/page/index.html'
@@ -36,7 +36,7 @@ declare global {
}
export const defaultPlaygroundURL = new URL(
`http://localhost:${process.env.CI ? 4173 : 5173}/starter/`
`http://localhost:${process.env.CI ? 4173 : 5173}/`
);
const NEXT_FRAME_TIMEOUT = 50;