Indent/Undent Nodes



I am trying to implement indent/undent nodes using tab for paragraphs.

For paragraphs I am just pre-pending 4 spaces for indent and removing 4 spaces (if they exist) for undent.

I have it working for single lines but for multi line selections I am not sure how to get the selected nodes.

Something like this would be great:$from, $to) 

Which could return an array of nodes based on the selection [node1, node2, …];

Once I have this i can apply the insertText of 4 spaces on each line.

Is there a way to get the selected nodes and iterate over them?

Also if there is a universal way to indent paragraphs that would be better than adding whitespace.

Also list items indent without creating a sublist would also be a great feature.

Eg just indent without any style change to the bullet.



I was able to get access to the nodes in question using nodesAt(index)

Now I am struggling to combine multiple transactions for insertText() on multiple lines

It works fine on a single line but im not sure how to apply many transactions of insertText.

Any ideas how this would be done?

I tried:

tr.step(new ReplaceAroundStep(currentStart, currentStart, 0, 0, new Slice(newFragment, 0, 0), 0, false));

but I am not sure how to build the newFragment or if ReplaceAroundStep is the right approach

Thanks in advance


I think nodesBetween with a little filtering can be made to do what you want here.

I’d lean towards adding an indentation attribute on the nodes and changing their styling based on that.


Hi @marijn. I am trying to implement indent/unindent too so I followed your advice. I added an indentation attribute to the node spec for paragraphs and it worked. When I hit Enter at the end of an indented paragraph though the new paragraph is not indented, that is it loses the attributes of the first paragraph. I fixed that by copying the splitBlock function and adding a few bits to it but overall it feels strange that the new paragraph does not keep the attributes of the one from which it was split.


If you split a paragraph in the middle, you’ll get a new paragraph with the same attributes. But when you press enter at the end splitBlock will create a fresh node (using the default content type at that position), so that when you press enter at the end of a heading or similar block, you get a plain paragraph.