UNPKG

@tiptap/extension-collaboration

Version:

collaboration extension for tiptap

150 lines (148 loc) 4.81 kB
// src/collaboration.ts import { Extension } from "@tiptap/core"; import { Plugin, PluginKey } from "@tiptap/pm/state"; import { redo, undo, ySyncPlugin, yUndoPlugin, yUndoPluginKey, yXmlFragmentToProsemirrorJSON } from "@tiptap/y-tiptap"; var Collaboration = Extension.create({ name: "collaboration", priority: 1e3, addOptions() { return { document: null, field: "default", fragment: null, provider: null }; }, addStorage() { return { isDisabled: false }; }, onCreate() { if (this.editor.extensionManager.extensions.find((extension) => extension.name === "undoRedo")) { console.warn( '[tiptap warn]: "@tiptap/extension-collaboration" comes with its own history support and is not compatible with "@tiptap/extension-undo-redo".' ); } }, addCommands() { return { undo: () => ({ tr, state, dispatch }) => { tr.setMeta("preventDispatch", true); const undoManager = yUndoPluginKey.getState(state).undoManager; if (undoManager.undoStack.length === 0) { return false; } if (!dispatch) { return true; } return undo(state); }, redo: () => ({ tr, state, dispatch }) => { tr.setMeta("preventDispatch", true); const undoManager = yUndoPluginKey.getState(state).undoManager; if (undoManager.redoStack.length === 0) { return false; } if (!dispatch) { return true; } return redo(state); } }; }, addKeyboardShortcuts() { return { "Mod-z": () => this.editor.commands.undo(), "Mod-y": () => this.editor.commands.redo(), "Shift-Mod-z": () => this.editor.commands.redo() }; }, addProseMirrorPlugins() { var _a; const fragment = this.options.fragment ? this.options.fragment : this.options.document.getXmlFragment(this.options.field); const yUndoPluginInstance = yUndoPlugin(this.options.yUndoOptions); const originalUndoPluginView = yUndoPluginInstance.spec.view; yUndoPluginInstance.spec.view = (view) => { const { undoManager } = yUndoPluginKey.getState(view.state); if (undoManager.restore) { undoManager.restore(); undoManager.restore = () => { }; } const viewRet = originalUndoPluginView ? originalUndoPluginView(view) : void 0; return { destroy: () => { const hasUndoManSelf = undoManager.trackedOrigins.has(undoManager); const observers = undoManager._observers; undoManager.restore = () => { if (hasUndoManSelf) { undoManager.trackedOrigins.add(undoManager); } undoManager.doc.on("afterTransaction", undoManager.afterTransactionHandler); undoManager._observers = observers; }; if (viewRet == null ? void 0 : viewRet.destroy) { viewRet.destroy(); } } }; }; const ySyncPluginOptions = { ...this.options.ySyncOptions, onFirstRender: this.options.onFirstRender }; const ySyncPluginInstance = ySyncPlugin(fragment, ySyncPluginOptions); if (this.editor.options.enableContentCheck) { (_a = fragment.doc) == null ? void 0 : _a.on("beforeTransaction", () => { try { const jsonContent = yXmlFragmentToProsemirrorJSON(fragment); if (jsonContent.content.length === 0) { return; } this.editor.schema.nodeFromJSON(jsonContent).check(); } catch (error) { this.editor.emit("contentError", { error, editor: this.editor, disableCollaboration: () => { var _a2; (_a2 = fragment.doc) == null ? void 0 : _a2.destroy(); this.storage.isDisabled = true; } }); return false; } }); } return [ ySyncPluginInstance, yUndoPluginInstance, // Only add the filterInvalidContent plugin if content checking is enabled this.editor.options.enableContentCheck && new Plugin({ key: new PluginKey("filterInvalidContent"), filterTransaction: () => { var _a2; if (this.storage.isDisabled !== false) { (_a2 = fragment.doc) == null ? void 0 : _a2.destroy(); return true; } return true; } }) ].filter(Boolean); } }); // src/helpers/isChangeOrigin.ts import { ySyncPluginKey } from "@tiptap/y-tiptap"; function isChangeOrigin(transaction) { return !!transaction.getMeta(ySyncPluginKey); } // src/index.ts var index_default = Collaboration; export { Collaboration, index_default as default, isChangeOrigin }; //# sourceMappingURL=index.js.map