import { DOMSerializer, Fragment, Node as ProsemirrorNode } from "prosemirror-model"; import { EditorState } from "prosemirror-state"; import { Transform } from "prosemirror-transform"; import { getPluginStateOrThrow } from "./RangePlugin"; import { EditorSchema, ClipboardRangeAttr } from "../schema"; export class RangeClipboardSerializer implements DOMSerializer { private readonly domSerializer = DOMSerializer.fromSchema(this.schema); public readonly nodes = this.domSerializer.nodes; public readonly marks = this.domSerializer.marks; constructor(private readonly schema: EditorSchema, private readonly getEditorState: () => EditorState) {} serializeFragment(_: Fragment, options?: { [key: string]: string }) { const state = this.getEditorState(); const rangePluginState = getPluginStateOrThrow(state); // Create a new tranform doc const transform = new Transform(state.doc); // Apply the range marks rangePluginState.sortedRanges.forEach(range => { transform.addMark( range.from, range.to, state.schema.marks.cr.create({ [ClipboardRangeAttr.ID]: range.id, [ClipboardRangeAttr.TYPE]: range.type, [ClipboardRangeAttr.ATTRS]: range.attrs }) ); }); // Create a new slice const updatedSlice = transform.doc.slice(state.selection.from, state.selection.to); return this.domSerializer.serializeFragment(updatedSlice.content, options) } serializeNode(node: ProsemirrorNode, options?: { [key: string]: string }): Node { return this.domSerializer.serializeNode(node, options) } }