src/ts/invisibles/node.ts (44 lines of code) (raw):

import { Node } from "prosemirror-model"; import createDeco from "../utils/create-deco"; import AddDecorationsForInvisible, { BuilderTypes } from "../utils/invisible"; export const createInvisibleDecosForNode = ( type: string, toPosition: (node: Node, pos: number) => number, predicate: (node: Node) => boolean, ): AddDecorationsForInvisible => ({ type: BuilderTypes.NODE, createDecorations: ( from, to, doc, decos, selection, shouldMarkAsSelected, ) => { let newDecos = decos; doc.nodesBetween(from, to, (node, pos) => { if (predicate(node)) { const decoPos = toPosition(node, pos); const oldDecos = newDecos.find( pos, pos + node.nodeSize - 1, (deco) => deco.type === type, ); // When we render invisibles that appear at the end of lines, mark // them as selected where appropriate. const selectionIsCollapsed = selection?.from === selection?.to; const isWithinCurrentSelection = selection && decoPos >= selection.from && decoPos <= selection.to; const selectionIsLongerThanNode = !!isWithinCurrentSelection && selection.to >= pos + node.nodeSize; const markAsSelected = shouldMarkAsSelected && selectionIsLongerThanNode && !selectionIsCollapsed; newDecos = newDecos .remove(oldDecos) .add(doc, [createDeco(decoPos, type, markAsSelected)]); return false; } }); return newDecos; }, });