# How to convert a selection of text lines into paragraphs?

**URL:** <https://discuss.prosemirror.net/t/how-to-convert-a-selection-of-text-lines-into-paragraphs/6099>\
**Category:** Uncategorized\
**Created:** [January 11, 2024, 7:34pm UTC](https://discuss.prosemirror.net/t/how-to-convert-a-selection-of-text-lines-into-paragraphs/6099 "2024-01-11T19:34:18Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rfgamaral](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/rfgamaral/32/2437_2.png) [@rfgamaral](https://discuss.prosemirror.net/u/rfgamaral)\
**Post date:** [January 11, 2024, 7:34pm UTC](https://discuss.prosemirror.net/t/how-to-convert-a-selection-of-text-lines-into-paragraphs/6099/1 "2024-01-11T19:34:18Z")

</div>

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](https://discuss.prosemirror.net/uploads/secondsite/original/2X/c/cd210be6932030578a9a98984ef898214b310ed7.png)

⬇

![image](https://discuss.prosemirror.net/uploads/secondsite/original/2X/4/42e48813689ddf92ddbea920211348979480c7a7.png)

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

---

<div class="post-metadata">

**Author:** ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)\
**Post date:** [January 12, 2024, 9:34am UTC](https://discuss.prosemirror.net/t/how-to-convert-a-selection-of-text-lines-into-paragraphs/6099/2 "2024-01-12T09:34:56Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![rfgamaral](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/rfgamaral/32/2437_2.png) [@rfgamaral](https://discuss.prosemirror.net/u/rfgamaral)\
**Post date:** [January 12, 2024, 5:52pm UTC](https://discuss.prosemirror.net/t/how-to-convert-a-selection-of-text-lines-into-paragraphs/6099/3 "2024-01-12T17:52:52Z")

</div>

> “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.

---

<div class="post-metadata">

**Author:** ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)\
**Post date:** [January 12, 2024, 6:28pm UTC](https://discuss.prosemirror.net/t/how-to-convert-a-selection-of-text-lines-into-paragraphs/6099/4 "2024-01-12T18:28:42Z")

</div>

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).

---

<div class="post-metadata">

**Author:** ![rfgamaral](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/rfgamaral/32/2437_2.png) [@rfgamaral](https://discuss.prosemirror.net/u/rfgamaral)\
**Post date:** [January 13, 2024, 2:56am UTC](https://discuss.prosemirror.net/t/how-to-convert-a-selection-of-text-lines-into-paragraphs/6099/5 "2024-01-13T02:56:34Z")

</div>

Awesome, exactly what I was looking for 🤩

I ended up with something like this:

```js
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?
