/** * Surgical reconcile — apply an authoritative external document into the live * editor by replacing only the changed top-level node run, instead of a * whole-document `setContent`. * * Why: under the Collaboration extension, `setContent` routes through * y-prosemirror and rewrites the ENTIRE `Y.XmlFragment`. Every block-level * NodeView is torn down and recreated (each `ReactRenderer` constructor calls * `flushSync`, firing inside a React lifecycle), remote carets jump, and the * CRDT sees a delete-all + insert-all instead of a small edit. Diffing the * top-level children and dispatching one `tr.replaceWith(from, to, changed)` * leaves unchanged NodeViews untouched and produces minimal Yjs ops. * * This is the core mechanism behind re-enabling single-doc collab in the plan * editor (see templates/plan/shared/plan-doc.collab-stability.spec.ts, "Option * B") and removing agent-edit NodeView churn in content. */ import type { Node as ProseMirrorNode } from "@tiptap/pm/model"; import type { Editor } from "@tiptap/react"; /** * Transaction meta marking programmatic (non-user) rich-markdown transactions. * Declared here (not in useCollabReconcile) so the module dependency stays * one-directional; useCollabReconcile re-exports it for consumers. */ export declare const RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION = "an-rich-md-programmatic-transaction"; export interface TopLevelDiff { /** Index of the first differing top-level child. */ fromIndex: number; /** Exclusive end index of the differing run in the OLD doc. */ oldToIndex: number; /** Exclusive end index of the differing run in the NEW doc. */ newToIndex: number; /** Document position where the differing run starts. */ fromPos: number; /** Document position where the differing run ends in the OLD doc. */ toPos: number; } /** * Diff two documents at top-level-node granularity: trim the common prefix and * suffix (node equality via ProseMirror's `Node.eq`, which is deep) and return * the remaining changed run. Returns null when the documents are equal. */ export declare function diffTopLevel(oldDoc: ProseMirrorNode, newDoc: ProseMirrorNode): TopLevelDiff | null; /** * Replace only the changed top-level run of the live document with the * corresponding run from `newDoc`, in one programmatic, history-free * transaction. Returns: * - "applied" — a targeted replacement was dispatched * - "noop" — the documents were already equal (nothing dispatched) * - "failed" — the diff/transaction could not be applied (schema mismatch, * invalid content, …); caller should fall back to setContent. */ export declare function applyDocSurgically(editor: Editor, newDoc: ProseMirrorNode): "applied" | "noop" | "failed"; /** * Best-effort default parser for the surgical path: use the tiptap-markdown * storage parser (present when the shared editor's `features.markdown` is on) * to turn the authoritative markdown into a ProseMirror document. Returns null * when unavailable or when parsing fails — the caller falls back to the full * `setContent` path. * * Apps with their own serializers (Content's NFM, Plan's blocks[] doc) should * pass an explicit `parseValue` producing the exact doc their `setContent` * would have written. */ export declare function defaultParseValue(editor: Editor, value: string): ProseMirrorNode | null; //# sourceMappingURL=surgical-apply.d.ts.map