HubSpot / draft-convert

Extensibly serialize & deserialize Draft.js ContentState with HTML.
Apache License 2.0
483 stars 94 forks source link

convertFromHTML with empty string returns results that can't be used with createFromBlockArray #157

Open hgezim opened 5 years ago

hgezim commented 5 years ago

I have this:

htmlToDraft(html: string) {
  const { contentBlocks } = convertFromHTML(html);
  return ContentState.createFromBlockArray(contentBlocks);
}

When I use the resulting content state to create an editor instance, it throws:

TypeError: contentState.getBlockMap(...).first(...) is undefined createWithContent ./node_modules/draft-js/lib/EditorState.js:55

52 | }; 53 | 54 | EditorState.createWithContent = function createWithContent(contentState, decorator) {

55 | var firstKey = contentState.getBlockMap().first().getKey(); | ^ 56 | return EditorState.create({ 57 | currentContent: contentState, 58 | undoStack: Stack(),

getEditorBaseState ./components/RecipePage.tsx:164

161 | }, 162 | ]); 163 |

164 | return EditorState.createWithContent(state, decorator); | ^ 165 | } 166 | 167 | private getDefaultContentState(type: ContentBlockType): ContentState {

mstoltenburg commented 5 years ago

I run into the same problem. It's even true for empty tags like <p></p> or <em></em> - the contentBlocks array is empty then.

import { EditorState, ContentState, convertFromHTML } from 'draft-js';

function createContentStateFromHtml(html) {
    const { contentBlocks, entityMap } = convertFromHTML(html);
    return ContentState.createFromBlockArray(contentBlocks, entityMap);
}

const content = createContentStateFromHtml('<p></p>');
const editor = EditorState.createWithContent(content);
// throws TypeError: contentState.getBlockMap(...).first(...) is undefined

// for now I am using this:
const editor = content.getBlockMap().size
        ? EditorState.createWithContent(content)
        : EditorState.createEmpty();

So there is a difference between ContentState.createFromText called with an empty string and ContentState.createFromBlockArray using convertFromHTML on an empty string.

const { contentBlocks, entityMap } = convertFromHTML('');

// ContentState.createFromText('').blockMap.size === 1
// ContentState.createFromBlockArray(contentBlocks, entityMap).blockMap.size === 0
mstoltenburg commented 5 years ago

Similar to the above, and also somehow unexpected:

import { ContentState, convertFromHTML } from 'draft-js';

const { contentBlocks, entityMap } = convertFromHTML('<p></p>');
const content = ContentState.createFromBlockArray(contentBlocks, entityMap);
const hasText = content.hasText();

// throws TypeError: blockMap.first(...) is undefined