import { Node } from "prosemirror-model"; import { NodeSelection, Transaction } from "prosemirror-state"; import * as pquery from "../pquery"; import { EditorSchema, schema } from "../schema"; import { isTextSelection } from "../util"; import { WedgeSelection } from "../wedge/WedgeSelection"; import { AttachmentAttrs } from "./schema"; /** * Toggle whether an attachment preview is shown. */ export function toggleHidePreview(tr: Transaction, pos: number): void { const attachment = tr.doc.resolve(pos).nodeAfter!; const { hp, ...otherAttrs } = attachment.attrs as AttachmentAttrs; // Using `undefined` for "off" to serialise more efficiently to JSON. const newAttrs: AttachmentAttrs = { ...otherAttrs, hp: hp === true ? undefined : true }; tr.setNodeMarkup(pos, undefined, newAttrs); } export function remove(tr: Transaction, pos: number): void { tr.delete(pos, pos + 1); } export function insertAttachment(tr: Transaction, nearPos: number, attachmentNode: Node): void { // Determine if, after inserting the attachment, the selection should be // changed to a node selection of the newly inserted attachment. const shouldSelectAttachment = (isTextSelection(tr.selection) && tr.selection.$cursor != null) || tr.selection instanceof WedgeSelection; let searchStart = nearPos; const $pos = tr.doc.resolve(nearPos); const { node: grandParentNode, index: grandParentIndex } = pquery.grandParent($pos); if ( $pos.parent.type === schema.nodes.p && grandParentNode.contentMatchAt(grandParentIndex).matchType(schema.nodes.at) != null ) { const p = $pos.parent; const pPos = $pos.before(); const pStart = $pos.start(); if (p.content.size === 0) { // Cursor in an empty paragraph. tr.replaceWith(pPos, pPos + p.nodeSize, attachmentNode); searchStart = pPos; } else if (nearPos === pStart) { // Cursor at the start of a paragraph. tr.insert(pPos, attachmentNode); searchStart = pPos; } else if (nearPos === pStart + p.content.size) { // Cursor at the end of a paragraph. tr.insert(pPos + p.nodeSize, attachmentNode); } else { // Cursor in the middle of a non-empty paragraph. tr.insert(nearPos, attachmentNode); } } else { tr.insert(nearPos, attachmentNode); } if (shouldSelectAttachment) { const found = pquery.findForward(tr.doc.resolve(searchStart), node => node === attachmentNode); if (found !== null) { tr.setSelection(new NodeSelection(found.$pos)); } } }