draft.js: how to preserve paragraph breaks when pasting content?
Asked Answered
J

2

10

Is there documentation that explains how to preserve paragraph breaks when content is pasted into draft.js? Other formating looks reasonable but all the paragraph blocks are collapsed into a single paragraph block when pasting.

Jaunitajaunt answered 19/8, 2016 at 21:20 Comment(9)
try github.com/sstur/draft-js-import-html, which help you import html.Rudie
No, draft-js-import-html is no help in this case. (I use draft-js-import-html already to convert HTML to editorState for loading content -- works fine). But that's no help when pasting content from another app: all the paragraph separators get stripped out.Jaunitajaunt
pasting html string or plain text?Rudie
Not plain text, but text copied to the clip board from any other application that uses rich text. Pasting such text into TInyMCE, Quil, CKEditor, etc. all preserve both inline formatting and paragraphs. Pasting into draft.js removes the line breaks, so that the entire pasted text is a single paragraph.Jaunitajaunt
draft only process plain text or html.Rudie
"draft only process plain text or html" -- Actually this is incorrect. Draft.js itself processes neither. It has it's own internal format (read the docs), but one may convert other formats (plain text, HTML, RTF, or whatever) to the internal format. The problem here is there is no obvious method to intercept a paste and do the translation before the pasted text is inserted.Jaunitajaunt
yes I mean 'process pasting plain text or html' actually.Rudie
I believe it was a design decision. If you copy a big block of text from another editor, it's probably going to insert a newline after each line of text in the paragraph. So instead, they parse them out. github.com/facebook/draft-js/issues/231Struble
@Jaunitajaunt Did you ever figure out how to preserve paragraphs? I'm trying to do that in react-rte - github.com/sstur/react-rteGoing
I
7

You can handle this using a prop for Editor.

handlePastedText = (text: string, html?: string, editorState: EditorState) => {
    const selection = editorState.getSelection();
    const pastedBlocks = ContentState.createFromText(text).blockMap;
    const newState = Modifier.replaceWithFragment(
        editorState.getCurrentContent(),
        editorState.getSelection(),
        pastedBlocks,
    );
    const newEditorState = EditorState.push(editorState, newState, "insert-fragment");
    this.handleChange(newEditorState);
    return "handled";
};

And then pass this as props in Editor. This will solve your problem.

Inelegant answered 4/10, 2019 at 10:51 Comment(0)
M
3

Unfortunately, there is no public documentation of processing of pasted content. But since draft-js is open-sourced, reading the sources comes to the rescue.

Draft-js 0.9.1 and below

Just specify p as aliased element for unstyled block using blockRenderMap:

import { Map } from 'immutable';
import Editor from 'draft-js';

const customRenderMap = Map({
  unstyled: {
    element: 'div',
    // will be used in convertFromHTMLtoContentBlocks
    aliasedElements: ['p'],
  },
});

<Editor
  editorState={this.state.editorState}
  blockRenderMap={customRenderMap}
/>

Explanation:

When you paste content to draft-js, editOnPaste function gets invoked. Inside it draft determines that content you pasted is html (yes, when you copy-paste any text from text processors like MS Word, Google Docs or Apple Pages, it's actually html), and calls convertFromHTMLToContentBlocks().

convertFromHTMLToContentBlocks() in its turn uses blockRenderMap to determine how to split html to blocks.

Draft-js 0.10.0

div is aliased with p by default in [email protected]

Meneses answered 18/3, 2017 at 18:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.