If you are dealing with an input field or a textarea, we can easily represent the input as a simple String. But how does Draft.js represent a rich text data that has all sorts of styles, blocks, entities (like links, emojis) and more?
This becomes useful as we need to ultimately extract the data from the editor, save it into a DB, retrieve it back and display it somewhere else with ALL the formatting intact!
Thankfully Draft.js provides a function called convertToRaw(for exporting data) and convertFromRaw(for importing data).
Let’s say we exported the data from an example Draft.js editor(https://react-rte.org) shown in Picture 1 using “convertToRaw”, the JSON output will look like as shown in Picture 2.
You can click on the pictures to zoom.
You can find various example editors and their source here: https://draftjs-examples.herokuapp.com/
Obviously the above JSON is unreadable 😋, let’s understand it better by looking at in smaller chunks.
The JSON output has two main parts: 1. blocks 2. entityMap. A block is analogous to a single line of data w/o newline(i.e could be a long wrapped line or a paragraph). And since there can be multiple blocks or lines of data, they are represented in an array called “blocks”.
entityMaps And entityRanges
A block of data can contain entities like links, mentions, hashtags and so on. For this example, let’s take a classic link.
A classic link is styled as blue, underlined text that, when clicked, will navigate the browser somewhere. And there can be multiple links, mentions and other entities.
Draft.js supports links out of the box but it needs to know how many characters (length), which characters (offset) to format characters as links. This information is stored in entityRange. But since there can be multiple links and other entities(like hashtags, mentions) in a given block, this information for each each is kept in an array called entityRanges within a given block.
Now, links are not just simple texts with styles, they can also have additional data like href urls, these additional data are kept in an object called entityMap with a key(e.g. 0, 1, 2). EntityMaps also have additional properties like mutability(changes how editor behaves) and type(type of the entity).
Inline Styles are just regular styles we add to the text. These styles are represented at a character-level since every single character can have it’s own style(or even multiple styles). To be efficient, Draft.js organizes set of consecutive characters w/ same styles(or same set of styles) in a single object called inlineStyleRanges. To be clear, this is ONLY organized like this in the “convertToRaw” output (for brevity). In actual contentState it is stored the long way for each character.
“blocks” can also have depths. Depths are usually used to represent sub-item or sub-sub-item typically seen in lists like shown below.
Custom Entities And Decorators
There are also other things called Decorators that use regex to format data at run-time and generate entities. For example: If you enter a “#hastag”, it shows up as a link instantly in the editor itself but may not be exported or may be exported by apps outside of the editor (depends on how it’s implemented).
Export To HTML
In many cases, you may not want JSON but want a HTML output. At this point there is no official HTML exporter but there are couple open source projects that may work for you:
Thanks to Simon Sturmer for reviewing this and for the awesome editor!
My Other Blogs
- Webpack — The Confusing Parts
- Webpack & Hot Module Replacement [HMR]
- Webpack’s HMR And React-Hot-Loader — The Missing Manual
React And Redux :
- Step by Step Guide To Building React Redux Apps
- A Guide For Building A React Redux CRUD App (3-page app)
- Using Middlewares In React Redux Apps
- Adding A Robust Form Validation To React Redux Apps
- Securing React Redux Apps With JWT Tokens
- Handling Transactional Emails In React Redux Apps
- The Anatomy Of A React Redux App
🎉🎉🎉 If you like this post, please 1. ❤❤❤ it below on Medium and 2. please share it on Twitter. You may retweet the below card🎉🎉🎉
Thanks for reading!!😀🙏