# How to preserve hard breaks when pasting HTML into a plain-text schema?

**URL:** <https://discuss.prosemirror.net/t/how-to-preserve-hard-breaks-when-pasting-html-into-a-plain-text-schema/4202>\
**Category:** Uncategorized\
**Created:** [November 17, 2021, 9:08pm UTC](https://discuss.prosemirror.net/t/how-to-preserve-hard-breaks-when-pasting-html-into-a-plain-text-schema/4202 "2021-11-17T21:08:09Z")\
**Posts on this page:** 6\
**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:** [November 17, 2021, 9:08pm UTC](https://discuss.prosemirror.net/t/how-to-preserve-hard-breaks-when-pasting-html-into-a-plain-text-schema/4202/1 "2021-11-17T21:08:09Z")

</div>

I’m using ProseMirror with a very basic schema:

- A document node that only accepts inline elements (no paragraphs)
- Hard breaks (i.e., `<br>`), and `Enter` is tweaked to insert line breaks
- And text nodes, of course

The idea here is to have plain-text editor augmented with extensions such as mentions (which are also inline elements).

However, I’m having an issue when I paste HTML content (for instance, copying code from VS Code and pasting into a ProseMirror editor). The content is pasted succesfully, but line breaks are ignored and the text is pasted into a single line.

What’s the best way to work around this? What’s the best event handler for this? Would love some pointers in the right direction, as I’m a bit clueless.

Thank you.

---

<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:** [November 17, 2021, 9:26pm UTC](https://discuss.prosemirror.net/t/how-to-preserve-hard-breaks-when-pasting-html-into-a-plain-text-schema/4202/2 "2021-11-17T21:26:24Z")

</div>

I’m guessing the pasted HTML contains either newlines or block nodes wrapping the text, instead of `<br>` nodes? You could try using [`transformPastedHTML`](https://prosemirror.net/docs/ref/#view.EditorProps.transformPastedHTML) to pre-process it into something your scheme’s DOM parser can handle.

---

<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:** [November 17, 2021, 10:36pm UTC](https://discuss.prosemirror.net/t/how-to-preserve-hard-breaks-when-pasting-html-into-a-plain-text-schema/4202/3 "2021-11-17T22:36:33Z")

</div>

That was my first approach, but my problem is how to process that while knowing where to insert `<br>`. For instance, take this basic implementation:

```auto
transformPastedHTML(html) {
    const doc = new DOMParser().parseFromString(html, 'text/html')
    return doc.body.textContent || ''
},

```

And this input from VS Code:

```auto
class ExtendedDispatcher extends Dispatcher<Action> {
    dispatch(payload: Action) {
    }
}

```

And I get this output:

```nohighlight
class ExtendedDispatcher extends Dispatcher<Action> { dispatch(payload: Action) { }}

```

New lines were lost, and it’s hard to figure out where to insert the `<br>` elements.

---

<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:** [November 17, 2021, 10:49pm UTC](https://discuss.prosemirror.net/t/how-to-preserve-hard-breaks-when-pasting-html-into-a-plain-text-schema/4202/4 "2021-11-17T22:49:12Z")

</div>

I think I’ve done some progress:

```auto
transformPastedHTML(html) {
    const document = new DOMParser().parseFromString(html, 'text/html')

    const textLines: string[] = []

    document.body.firstElementChild?.childNodes.forEach((childNode) => {
        textLines.push(childNode.textContent || '')
    })

    return textLines.join('<br>')
},

```

It’s still not finished, because it’s stripping spaces (imagine indented code), which I don’t want. Will need to look further into this tomorrow. But I’m open to ideas/improvements on this 🙂

---

<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:** [November 18, 2021, 9:22am UTC](https://discuss.prosemirror.net/t/how-to-preserve-hard-breaks-when-pasting-html-into-a-plain-text-schema/4202/5 "2021-11-18T09:22:46Z")

</div>

@marijn With the solution above, I wasn’t able to preserve spaces from pasted text for some reason (I have initialized the editor with `preserveWhitespace: true`), so I had to find a different solution.

Here’s what I came up with:

```auto
handlePaste(view, event) {
    const { state } = view
    const { tr } = state

    if (!state.schema.nodes.hardBreak) {
        return false
    }

    const clipboardText = event.clipboardData?.getData('text/plain').trim()

    if (!clipboardText) {
        return false
    }

    const textLines = clipboardText.split(/(?:\r\n|\r|\n)/g)

    const nodes = textLines.reduce<Node[]>((nodes, line, index) => {
        if (line.length > 0) {
            nodes.push(state.schema.text(line))
        }

        if (index < textLines.length - 1) {
            nodes.push(state.schema.nodes.hardBreak.create())
        }

        return nodes
    }, [])

    view.dispatch(
        tr.replaceSelection(Slice.maxOpen(Fragment.fromArray(nodes))).scrollIntoView(),
    )

    return true
}

```

Advantages of this implementation:

- It works for both pasted text and pasted HTML (getting the `text/plain` data from the clipboard comes without HTML and spaces preserved).
- I had `clipboardTextParser` overridden to do the same thing for plain-text, and now I have one solution that works for both.

I’m open to any suggestions you might have to improve this code further 🙂

---

<div class="post-metadata">

**Author:** ![minseoksuh](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/minseoksuh/32/3803_2.png) [@minseoksuh](https://discuss.prosemirror.net/u/minseoksuh)\
**Post date:** [December 7, 2023, 11:43am UTC](https://discuss.prosemirror.net/t/how-to-preserve-hard-breaks-when-pasting-html-into-a-plain-text-schema/4202/6 "2023-12-07T11:43:05Z")

</div>

Thank you for the code. Worked like a charm.
