In the last couple of years I have found myself in a couple of projects using web based rich text editors. Since these projects were written using React, I primarily focused on libraries that worked with that framework but have been keeping an eye on other projects as well. This post is a braindump of my thoughts on the space
mailto: link. With the advent of contentEditable, we thought this would be easy to do
We were totally wrong. Turned out contentEditable is a terrible API as documented in this article by the Medium engineering team. Modifying the underlying document while the user was editing it was just impossible to get right even on one browser. And for bonus pain points, every browser wrote different underlying HTML when the user edited a contentEditable element.
About 3 years ago I was assigned to work on an online CMS for an internal portal at work and started looking at RTEs again. Since the rest of the project was going to be in React, I started looking closely at React libraries. React had one advantage that didn’t exist when we had tried our earlier adventure: Since React keeps the document structure in its Virtual DOM, it didn’t have to fight with the browser specific implementations of contentEditable as well as fight the browser for things like cursor position and selections.
DraftJS seemed like the best choice at the time. It was (and still is) actively developed by Facebook and is used by them for text editors on Facebook.com.
Generally it worked well enough. We could have used more documentation but were able to get a default experience working. Draft comes with very few extensions and really tries to sell its “toolkit” nature by having you code behavior I’d have expected as default. There is a different project called DraftJS-Plugins that gives you a lot of that. Weirdly, DraftJS-Plugins requires you to use its Editor which seems to be a modified version of the DraftJS editor. Ideally Draft should support plugins out of the box.
We did make a mistake with storing the document though. Our thinking was that the document in the database should be saved as HTML and Draft should just re-render the HTML when the document needs to be edited. Turns out Draft really prefers saving and loading a serialized state of the document. This does make some sense but makes any future migrations to a different editor much harder. This brings me to the next library I looked at
Ghost is a pretty interesting CMS. Visually its very polished and the editor interface there is pretty amazing. Earlier versions of Ghost used an editor that really was centered around Markdown, which is awesome but not a fit for the target audience of our system. Ghost also had very limited database support: basically SQLite for development and MySQL for production. Since we didn’t want to use MySQL it was a deal breaker.
But from the point of view of Text Editors, Ghost 2.0 that was recently released shipped with a new and much nicer editor. The editor is now part of the main Ghost repo but I imagine can/should be extracted to its own project.
Whats really interesting about the Ghost Editor is that they also released a library for building WYSIWYG editors supporting rich content via cards called MobileDoc-Kit and an open source spec for these documents called MobileDoc. This addresses my issue with storing a proprietary format for a document in the database. So yay!
Meanwhile WordPress has also been working on their own new editor that just shipped as part of WordPress 5.0 today. In a big departure from previous PHP centric WordPress editors, Gutenburg is written in ReactJS. Additionally, unlike Draft (as well as Ghost 2.0 editor I think), Gutenburg works on mobile devices. My biggest issue is that I really hate WordPress’s “HTML comments as a data structure” approach. And I am not the only one. Using Gutenburg has so far been pretty okay. If you’d like to learn more about it, read Matt Mullenweg’s post on it today
Other projects also crossed my path during this project. CKEditor for example looks promising but I have’t dug into it. What makes it really interesting is its newly added support for collaborative editing out of the box, something I’d love to add to my project but its not a big ask (yet)
If Rails is your thing, Rails 6.0 will include a Rich Text Editor out of the box which is really cool. The editor itself, Trix, is out right now and can be added to your project if you need it.
Final Thoughts: Blocks
One interesting thing is that almost all the editors are starting to move into the concept of a rich document as a group of content blocks. This is a departure from earlier architectures that gave you the entire document as a rich document with all the formatting. One reason for this is the ability to export the content blocks in a variety of formats besides simple HTML (like Markdown).
Blocks also let you use non-text elements within the document. These can be things like media or even rich widgets like photo galleries etc. Given a well defined document data-structure, these can also be supplied by third-parties.
For example, Elementor has released a bunch of widgets for WordPress’s Gutenburg
Modern word processor centric startups are taking these ideas even further. For example,Notion takes the same block based approach to a person notes app
Both Notion and AirTable measure usage and price their plans not on the basis of number of documents but rather the number of blocks used.