Hi - I have been exploring prosemirror for a few days but I am struggling a bit on some parts - Whenever a user selects a bunch of text in the editor - I need to wrap the content with a custom node. There are 2 scenarios here -
- Selection is from the same parent
- The selection spans across multiple nodes.
I got the first part working by fiddling around the different examples - I created a command that replaces the Selection with a new node when it’s inside the same parent.
(state, dispatch) =>
{
const { schema, doc, tr } = state;
const { empty, $from, $to, from, to } = state.selection;
if(!empty && $from.sameParent($to) && $from.parent.inlineContent)
{
let content = $from.parent.content.cut($from.parentOffset, $to.parentOffset);
if(content)
{
const node = type.create({}, content);
dispatch(tr.replaceSelectionWith(node, attrs));
return true;
}
else
{
return false;
}
}
else if(!empty)
{
//Need to loop through the nodes part of the selection and replace them.
}
}
I’ve been playing around with the 2nd case but seems like I am missing something.
I tried looping through all the nodes and replacing them (which feels like a bad hack that might blowup in my face given my limited understanding of Prosemirror) - But I ran into the "RangeError: Applying a mismatched transaction"
as the document gets updated after the first transaction.
Also - The only way I knew on how to replace the node was to set a selection on it and replace it with "replaceSelectionWith"
let content = state.selection.content();
if(content && content.content && content.content.content)
{
let nodes = content.content.content;
let flag = false;
let newSelectionPoint = from;
let currentDoc = doc;
nodes.forEach((node) =>
{
flag = true;
let nodeContent = node.content;
let newNode = type.create({}, nodeContent);
let trx = tr.setSelection(new TextSelection(currentDoc.resolve(newSelectionPoint), currentDoc.resolve(newSelectionPoint + node.nodeSize -2 )));
dispatch(trx);
trx = tr.replaceSelectionWith(newNode, attrs);
dispatch(trx);
newSelectionPoint = newSelectionPoint + node.nodeSize + 1;
currentDoc = trx.doc;
})
}
So -
- How do I get back the updated document after the transaction? [Or how exactly do I dispatch multiple transactions from the command?]
- Is there an easier way to do this? (Seems like a common use case so not sure what I missed).
Thanks a ton!