Reputation: 7073
I am sure I am doing something wrong. However, a simply empty html tag is creating a problem with convertFromHTML call.
convertFromHTML("<p> </p>"); // returns null
Where as:
convertFromHTML("<p>empty</p>"); // returns a valid object.
Any thought son why it might be happening?
Upvotes: 0
Views: 1581
Reputation: 1
I faced the similar problem and solved it using draft-js v0.10.4. Hope this will work for you as well :)
Upvotes: 0
Reputation: 2307
convertFromHTML("<p> </p>"); // returns null
I'll assume "returns null" is meant literally in which case updating to the most recent draft-js
version should fix the problem.
Here's my example running
create-react-app
v1.5.2draft-js
v0.10.5console.log(convertFromHTML('<p> </p>'))
There is a "valid" object, but the contentBlocks
property is null
, which means we cannot create a valid ContentState
as you'll get the following:
TypeError: Cannot read property 'contentBlocks' of null
Any thoughts on why it might be happening?
Short Answer: The HTML node needs text.
In-Depth Answer:
All of the following code is adapted from the most recent version of draft-js
source at the time of this writing (commit 4c4465f). Some sections of methods are left out for brevity.
The method convertFromHTMLtoContentBlocks
is what's called by this module and it has a few main steps:
contentBlocks
object1) Processing the string to a DOM
The html gets processed by a method getChunkForHTML
the output from which the contentBlocks
is created.
const convertFromHTMLtoContentBlocks = (
html: string,
DOMBuilder: Function = getSafeBodyFromHTML,
blockRenderMap?: DraftBlockRenderMap = DefaultDraftBlockRenderMap,
): ?{contentBlocks: ?Array<BlockNodeRecord>, entityMap: EntityMap} => {
const chunkData = getChunkForHTML( // processing our html string into chunkData
html,
DOMBuilder,
blockRenderMap,
DraftEntity,
);
// use the chunkData to create contentBlocks
const {chunk, entityMap} = chunkData;
const contentBlocks = convertChunkToContentBlocks(chunk);
return {
contentBlocks,
entityMap,
};
};
Inspecting getChunkForHTML
, we see that the white-space is trimmed to <p></p>
and passed to DOMBuilder
. The DOM created by DOMBuilder
is converted into blocks by genFragment
, prettied and returned as chunk
.
const getChunkForHTML = (
html: string,
DOMBuilder: Function,
blockRenderMap: DraftBlockRenderMap,
entityMap: EntityMap,
): ?{chunk: Chunk, entityMap: EntityMap} => {
html = html // the string is trimmed
.trim()
.replace(REGEX_CR, '')
.replace(REGEX_NBSP, SPACE)
.replace(REGEX_CARRIAGE, '')
.replace(REGEX_ZWS, '');
const safeBody = DOMBuilder(html); // create DOM from trimmed html
if (!safeBody) {
return null;
}
const fragment = genFragment(
entityMap,
safeBody, // use DOM to create blocks in genFragment
OrderedSet(),
'ul',
null,
workingBlocks,
-1,
blockRenderMap,
);
let chunk = fragment.chunk;
const newEntityMap = fragment.entityMap;
// rest of method
return {chunk, entityMap: newEntityMap};
};
2) Create DOM from string
If we inspect the DOMBuilder
method (alias for getSafeBodyFromHTML
) (source) in the debugger, we see that we get a DOM node with these properties:
innerHTML: "<p></p>"
innerText:""
3) Generating Blocks from the DOM
The output of DOMBuilder
is an argument to genFragment
as safeBody
. This method processes the DOM tree into blocks. Given that our DOM contains no text, the object returned from genFragment
has the property: text: ""
.
4)Mapping the blocks to contentBlocks
The last call in the convertFromHTMLtoContentBlocks
is
const contentBlocks = convertChunkToContentBlocks(chunk);
:
const convertChunkToContentBlocks = (chunk: Chunk): ?Array<BlockNodeRecord> => {
if (!chunk || !chunk.text || !Array.isArray(chunk.blocks)) {
return null;
}
// rest of method
}
clearly, at this point chunk.text
returns false
and thus contentBlocks
is null
.
Upvotes: 7