@blocknote/core
Version:
A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.
90 lines (85 loc) • 3.07 kB
text/typescript
import type { Awareness } from "y-protocols/awareness";
import type * as Y from "yjs";
import type { BlockNoteEditorOptions } from "../../editor/BlockNoteEditor";
import {
createExtension,
type ExtensionOptions,
} from "../../editor/BlockNoteExtension.js";
import { FixUpSchemaExtension } from "./FixUpSchema.js";
import { ForkYDocExtension } from "./ForkYDoc.js";
import { RelativePositionMappingExtension } from "./RelativePositionMapping.js";
import { SchemaMigration } from "./schemaMigration/SchemaMigration.js";
import { CollaborationUser, YCursorExtension } from "./YCursorPlugin.js";
import { YSyncExtension } from "./YSync.js";
import { YUndoExtension } from "./YUndo.js";
export type CollaborationOptions = {
/**
* The Yjs XML fragment that's used for collaboration.
*/
fragment: Y.XmlFragment;
/**
* The user info for the current user that's shown to other collaborators.
*/
user: CollaborationUser;
/**
* A Yjs provider (used for awareness / cursor information)
*/
provider?: { awareness?: Awareness };
/**
* Optional function to customize how cursors of users are rendered
*/
renderCursor?: (user: CollaborationUser) => HTMLElement;
/**
* Optional flag to set when the user label should be shown with the default
* collaboration cursor. Setting to "always" will always show the label,
* while "activity" will only show the label when the user moves the cursor
* or types. Defaults to "activity".
*/
showCursorLabels?: "always" | "activity";
};
export const CollaborationExtension = createExtension(
({ options }: ExtensionOptions<CollaborationOptions>) => {
return {
key: "collaboration",
blockNoteExtensions: [
FixUpSchemaExtension(),
ForkYDocExtension(options),
RelativePositionMappingExtension(),
SchemaMigration(options),
YCursorExtension(options),
YSyncExtension(options),
YUndoExtension(),
],
} as const;
},
);
export function withCollaboration<
Options extends Partial<BlockNoteEditorOptions<any, any, any>>,
>(
options: Options & {
/**
* Options for configuring the collaboration functionality.
*/
collaboration: CollaborationOptions;
},
): Options {
return {
...options,
extensions: [
...(options.extensions ?? []),
CollaborationExtension(options.collaboration),
],
// We disable the default prosemirror history plugin, since it's not compatible with yjs
disableExtensions: ["history", ...(options.disableExtensions ?? [])],
// We don't want the default initial content, since it will generate a random id for the initial block on each client,
// leading to conflicts when syncing happens afterwards.
initialContent: [{ type: "paragraph", id: "initialBlockId" }],
};
}
export * from "./ForkYDoc.js";
export * from "./RelativePositionMapping.js";
export * from "./schemaMigration/SchemaMigration.js";
export * from "./Versioning.js";
export * from "./YCursorPlugin.js";
export * from "./YSync.js";
export * from "./YUndo.js";