How to convert a selection of text lines into paragraphs?

Hi there,

Imagine that I have multiple lines of text (single paragraph), and I want to convert the selection into paragraphs, while keeping the selection.

For instance, if a full paragraph was selected:

image

:arrow_down:

image

What would be the easiest way to build a command that does this?

“Lines” here means they are separated by hard break nodes? You could replace those with slices that close and re-open a paragraph.

“Lines” here means they are separated by hard break nodes?

Yes.

You could replace those with slices that close and re-open a paragraph.

Could you give me some pointers to which API calls I should be looking to achieve this? I’ve used slices before, but I’m a bit confused about the “that close and re-open a paragraph” part.

If you take a <p></p><p></p> fragment, and make it open on both sides, it’ll contain only the middle closing an opening tokens. Replacing inline content with that will insert a paragraph break.

So you run over the nodes in the selection, and replace hard breaks with such a slice. But you’ll want to do that back-to-front to compensate for the fact that such a replacement moves content after it forward by one position (since two tokens are bigger than one token).

Awesome, exactly what I was looking for :star_struck:

I ended up with something like this:

const hardBreaksPositions: number[] = []

tr.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
    if (node.type.name === 'hardBreak') { // I'm using Tiptap
        hardBreaksPositions.push(pos)
    }
})

hardBreaksPositions.reverse().forEach((pos) => {
    tr.replace(
        pos,
        pos + 1,
        Slice.maxOpen(
            Fragment.fromArray([
                schema.nodes.paragraph.create(),
                schema.nodes.paragraph.create(),
            ]),
        ),
    )
})

Would you do anything differently, @marijn? In other words, is there any optimization I can do here? For instance, is there a better way to traverse the nodes from $to.pos to $from.pos instead of storing them in an array and reverse it?