ProseMirror is a well-documented, but fairly nuanced, "toolkit for building rich-text editors." These are Bill's notes on how all the ProseMirror pieces fit together, with embedded examples where possible.
Given that I'm still very much a ProseMirror novice as of April 2021, some of this information is surely incorrect or misleading. But I'll be constantly updating it as more experienced PM experts suggest improvements.
dispatch generally: send off a transaction to EditorView to generate a new state, which will be stored (in the doc?)
NodeView can be used to control how either a node or a plugin is rendered into the html DOM
update called when PM determines that something in this node or plugins view has changed, so the view is updating itself.
node passed to
update may be anything that the editor's update algorithm might try to draw here, so you must verify that this is a node that this node view can handle [before acting on it in the
One widespread and kind of weird thing about position in ProseMirror is that, while they refer to indexes within the ProseMirror DOM, when you're providing the index for a node, you usually give the index one before the node's actual index. This is necessary because
nodeAfter will only return the node that you intend to refer to if they're given an index prior to that node.
tl; dr Often hard to get without mapping from starting document state through every transaction. Three options are using
Resolving the node before a given position: apparently
Resolving node after an index is the default
doc.nodeAt(pos), used often
Side exercise: Examining nodeAt
Dollar sign $ it would seem always/only used to indicate a ProseMirror ResolvedPos. Examples: $start, $end, $head, $anchor, $pos. It is unclear to Bill why this convention was chosen.
Use of a transaction meta key to indicate to a plugin when it should take action (emoji popper reading meta example as triggered here, file plugin reading meta example as set here from this originating caller that wants to store info about the current local/remote UUID of the file the
file-plugin is trying to display)
No examples found where a plugin tracks state of many instances
Decorations: Todo: learn how they interact
Alternate syntax, from the key
Have a type (inline, node, widget); they control aspects of how a node or view is shown without participating in the prosemirror dom
From the docs: "When the user types, or otherwise interacts with the view, it generates ‘state transactions’. Every state update has to go through updateState, and every normal editing update will happen by dispatching a transaction."
setMeta used to communicate over transactions between plugins/view/whatever else
Here's a piece of the method that updates local file UUIDs to remote file UUIDs, using setMeta to tell the history plugin not to mind the transaction it's going to generate
pos indexes that are one before where the corresponding
node appears to be within the ProseMirror document structure? It's tempting to think it would be so that
doc.resolve can be called on the position that's returned, and still select the desired
node? I.e., because
doc.resolve chooses the next node after the index given, perhaps these iteration functions return an index one prior to the element they're iterating to account for the behavior of doc.resolve?