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

@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:

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 :slight_smile:

1 Like