mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
feat(docs): bootstrapping using blocksuite (#2859)
This commit is contained in:
@@ -2,54 +2,52 @@
|
||||
import '@blocksuite/editor/themes/affine.css';
|
||||
|
||||
import { BlockSuiteEditor } from '@affine/component/block-suite-editor';
|
||||
import { ContentParser } from '@blocksuite/blocks/content-parser';
|
||||
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
||||
import { assertExists, Workspace } from '@blocksuite/store';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { useAtomValue } from 'jotai/react';
|
||||
import type { ReactElement } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { use } from 'react';
|
||||
import { applyUpdate } from 'yjs';
|
||||
|
||||
const workspace = new Workspace({
|
||||
id: 'local-workspace',
|
||||
})
|
||||
.register(AffineSchemas)
|
||||
.register(__unstableSchemas);
|
||||
|
||||
const page = workspace.createPage({
|
||||
id: 'example-page',
|
||||
});
|
||||
import { workspaceAtom } from '../atom.js';
|
||||
|
||||
export type EditorProps = {
|
||||
text: string;
|
||||
workspaceId: string;
|
||||
pageId: string;
|
||||
binary?: number[];
|
||||
onSave: (binary: any) => Promise<void>;
|
||||
};
|
||||
|
||||
export const Editor = (props: EditorProps): ReactElement => {
|
||||
return (
|
||||
<BlockSuiteEditor
|
||||
page={page}
|
||||
mode="page"
|
||||
onInit={useCallback(
|
||||
async page => {
|
||||
const text = props.text;
|
||||
await page.waitForLoaded();
|
||||
const metadata = text.split('---\n')[1];
|
||||
assertExists(metadata);
|
||||
const workspace = useAtomValue(workspaceAtom);
|
||||
let page = workspace.getPage('page0') as Page;
|
||||
if (!page) {
|
||||
page = workspace.createPage({
|
||||
id: 'page0',
|
||||
});
|
||||
}
|
||||
|
||||
// find title
|
||||
const title = metadata.split('title: ')[1]?.split('\n')[0];
|
||||
const pageBlockId = page.addBlock('affine:page', {
|
||||
title: new page.Text(title),
|
||||
});
|
||||
page.addBlock('affine:surface', {}, pageBlockId);
|
||||
const noteBlockId = page.addBlock('affine:note', {}, pageBlockId);
|
||||
const contentParser = new ContentParser(page);
|
||||
const content = text.split('---\n').splice(2).join('---\n');
|
||||
assertExists(content);
|
||||
await contentParser.importMarkdown(content, noteBlockId);
|
||||
page.awarenessStore.setReadonly(page, true);
|
||||
page.awarenessStore.setFlag('enable_drag_handle', false);
|
||||
},
|
||||
[props.text]
|
||||
)}
|
||||
/>
|
||||
);
|
||||
if (props.binary && !page.root) {
|
||||
use(
|
||||
page.waitForLoaded().then(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
applyUpdate(page._ySpaceDoc, new Uint8Array(props.binary as number[]));
|
||||
})
|
||||
);
|
||||
if (import.meta.env.MODE !== 'development') {
|
||||
page.awarenessStore.setReadonly(page, true);
|
||||
}
|
||||
} else if (!page.root) {
|
||||
use(
|
||||
page.waitForLoaded().then(() => {
|
||||
const pageBlockId = page.addBlock('affine:page', {
|
||||
title: new page.Text(''),
|
||||
});
|
||||
page.addBlock('affine:surface', {}, pageBlockId);
|
||||
const noteBlockId = page.addBlock('affine:note', {}, pageBlockId);
|
||||
page.addBlock('affine:paragraph', {}, noteBlockId);
|
||||
})
|
||||
);
|
||||
}
|
||||
return <BlockSuiteEditor page={page} mode="page" onInit={() => {}} />;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
'use server';
|
||||
|
||||
import { lazy } from 'react';
|
||||
|
||||
import { saveFile } from '../../server-fns.js';
|
||||
|
||||
const SaveToLocal = lazy(() =>
|
||||
import('./save-to-local.js').then(({ SaveToLocal }) => ({
|
||||
default: SaveToLocal,
|
||||
}))
|
||||
);
|
||||
|
||||
export const Sidebar = () => {
|
||||
return (
|
||||
<div
|
||||
@@ -11,6 +23,9 @@ export const Sidebar = () => {
|
||||
AFFiNE
|
||||
</div>
|
||||
</a>
|
||||
{import.meta.env.MODE === 'development' && (
|
||||
<SaveToLocal saveFile={saveFile} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
28
apps/docs/src/components/sidebar/save-to-local.tsx
Normal file
28
apps/docs/src/components/sidebar/save-to-local.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
'use client';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import { useAtomValue } from 'jotai/react';
|
||||
import { useCallback } from 'react';
|
||||
import { encodeStateAsUpdate } from 'yjs';
|
||||
|
||||
import { workspaceAtom } from '../../atom.js';
|
||||
|
||||
type SaveToLocalProps = {
|
||||
saveFile: (update: number[]) => void;
|
||||
};
|
||||
|
||||
export const SaveToLocal = (props: SaveToLocalProps) => {
|
||||
const workspace = useAtomValue(workspaceAtom);
|
||||
const saveFile = props.saveFile;
|
||||
const onSave = useCallback(() => {
|
||||
const page = workspace.getPage('page0');
|
||||
assertExists(page);
|
||||
saveFile([...encodeStateAsUpdate(page.spaceDoc)]);
|
||||
}, [saveFile, workspace]);
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center justify-center h-16 font-bold">
|
||||
<button onClick={onSave}>Save to Local</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user