When the cursor is in an empty heading block, I would like pressing “Enter” to reset it to a paragraph instead of advancing to a new line after the empty heading. A subsequent “Enter” would perform that usual action. I have been looking at the prosemirror-commands source for guidance, but am still learning and having trouble grokking the concepts. How might the implementation of such an action look?
When the cursor is in an empty heading block,
You can get the parent of the current selection by using state.selection.$from.parent
. Check it is a heading block by accessing the node’s type: node.type == state.schema.nodes.heading
, and then check if its empty: node.textContent.length == 0
.
I would like pressing “Enter” to reset it to a paragraph instead of advancing to a new line after the empty heading.
Use tr.setBlockType
to convert the heading to a paragraph node. The difficulty here will be using the state.selection.$from.parent
to find the from
and to
positions of the heading block.
Put together, the command should roughly look like:
export function HeadingToParagraph(state, dispatch) {
if (!state.selection.empty) return false;
let $from = state.selection.$from
if ($from.parent.type != state.schema.nodes.heading || $from.parent.textContent.length) return false;
// get bounds of heading block
let from = $from.pos - $from.parentOffset, to = from + $from.parent.nodeSize;
if (dispatch) dispatch(state.tr.setBlockType(from, to, state.schema.nodes.heading, {});
return true;
}
Then you want to attach it to an “Enter” key handler via prosemirror-keymap
.
If you only need to set one parent block, I think you can also use setBlockType
(part of prosemirror-commands module) instead of tr.setBlockType
and avoid getting the bounds of the heading block.