Problem
- change the code block content at the Embedded code editor example
- press
Mod-z
to undo the action - it only reverse the content change, but not the selection/cursor position (inside the codemirror)
Solution v1
refer to the discussion Problems when binding with codemirror6 we can set the selection when update the node view
this.cm.dispatch({
changes: {
from: start, to: curEnd,
insert: newText.slice(start, newEnd)
},
+ selection: { anchor: start + newText.slice(start, newEnd).length }
})
check out the online demo for this change
but this solution has some limits, for example it can’t support multiple selection inside the codemirror, and it just set the selection (cursor) after the reverse content, instead of undo to the previous selection state
Solution v2
maybe we can record the selection of the codemirror in the code_block
node attribute, and reload it when we need
the key point is convert the codemirror selection to JSON and sync to the code_block
node attribute, and deserialize the JSON to codemirror selection when update the nodeview
// serialized codemirror selection to JSON
const cmSelectionJSON = update.state.selection.toJSON();
const pos = this.getPos();
if(pos!==undefined) {
tr.setNodeAttribute(pos, 'selection', cmSelectionJSON);
}
this.cm.dispatch(
{
changes: {
from: start, to: curEnd,
insert: newText.slice(start, newEnd)
},
},
// load the selection record from code_block node attribute 'selection'
{
// deserialize a codemirror selection from JSON
selection: node.attrs.selection.hasOwnProperty('main') ? cmEditorSelection.fromJSON(node.attrs.selection) : undefined,
// based on the document after apply the above changes
sequential: true
}
)
check out the online demo for this change
and this solution can support multiple selection inside the codemirror
the relative issue in github