
Draft.js – Rich Text Editor Framework for React - tilt
http://facebook.github.io/draft-js/
======
marijn
My ProseMirror [1] project is in the same space (including using persistent
data model detached from the DOM). It has a richer, tree-shaped document model
and collaboration [2], but not quite as much programmerpower behind it since
I'm a single OSS dev as opposed to a giant tech company.

[1]: [https://prosemirror.net](https://prosemirror.net) [2]:
[http://marijnhaverbeke.nl/blog/collaborative-
editing.html](http://marijnhaverbeke.nl/blog/collaborative-editing.html)

~~~
JohnHammersley
Just wanted to take this opportunity to say thanks again for CodeMirror, and
it's great to see the progress you've been making with ProseMirror.

We use CM at Overleaf[1], and it's been fantastic. To make it easier for non-
LaTeX users to collaborate on LaTeX documents, we built our own rich text
editor on top of it[2], which is still in beta. Still got a long way to go!

[1] [https://www.overleaf.com](https://www.overleaf.com)

[2] [https://www.overleaf.com/blog/81](https://www.overleaf.com/blog/81)

~~~
DonHopkins
Oh yes, I want to say thank you too! I just discovered CodeMirror, and it's
wonderful. It was easy to make it to do just what I wanted, and it feels so
snappy (both fast, and easily plugged together with other code). I'll
definitely check out ProseMirror too.

~~~
amelius
How is CodeMirror different from ProseMirror?

~~~
nacs
The first is for code and the latter is for prose (non-code writing such as
this comment).

~~~
amelius
Okay, that makes sense.

But, then again, shouldn't a single editor be able to handle those two usage-
domains? (As this would mean the editor would be more powerful in terms of
extensibility).

~~~
atombender
Code is line-oriented and usually monospaced. Prose is not, and usually
requires local layout (spacing, alignment and so on), embedded media (such as
images) and variable typography.

------
bantic
(biased author of Mobiledoc-Kit here)

The past year or so has really seen a resurgence of browser-based text
editors. Off the top of my head I can think of 4 editors/editor-frameworks
launched in the past year (Mobiledoc-Kit, ProseMirror, Trix, and now
Draft.js). Browsers are creeping toward exposing all the events that are
necessary for interpreting the meaning of a user as they input text. (Some
notable exceptions remain, such as an event that would be fired when a
spelling correction is accepted, but mutation observers provide a fallback for
cases where it's not otherwise possible to catch the input on the way in.)

A major focus of Mobiledoc-Kit, which seems to have some overlap with
Draft.js, is on exposing an API that allows programmers to programmatically
interact with the internal (structured) document. Our goal is to allow
developers to be able to construct editors that fit snugly fit their use case,
whether that's building their own UI for a toolbar, or more complex procedural
rules for document (e.g., add a constraint that there can only be one "H1"
section in a document and disallow adding a second one).

Since Mobiledoc-Kit was built for a publisher originally (Bustle), the ability
to intersperse text with richer content was a goal from the start. So it has a
"card" concept that allows adding any rich content (embedded tweets, videos,
slidehows, etc.). In fact, the Mobiledoc-Kit demo page [1] has a demo where a
Codemirror editor is embedded inside the Mobiledoc editor.

It's great to see so much new energy in the browser editor world. I am hopeful
that as browser features and new editors and editor features converge, we'll
see some exciting new developments that broaden the perspective on what sort
of content is possible to author from within a web page.

[1]: [https://bustlelabs.github.io/mobiledoc-
kit/demo/](https://bustlelabs.github.io/mobiledoc-kit/demo/)

------
tomdale
For those of you looking for a rich text editor like this that is
lighterweight and doesn't come with a heavy React dependency, I can highly
recommend Mobiledoc[1]. I've been using it in several production sites and it
has performed like a champ.

The best part of Mobiledoc is its portability; I've seen it used in both
Ember.js and Riot.js, two libraries on opposite ends of the spectrum.

It's also been designed for rich, interactive content _in addition to_ rich
text. You can add interactive cards (think slideshows, before/after image
sliders, etc.) and easily provide a different implementation on each platform.
This lets your content authors write once and have a great experience on both
native and web, and adding a new card is super easy.

1: [https://github.com/bustlelabs/mobiledoc-
kit](https://github.com/bustlelabs/mobiledoc-kit)

~~~
mixonic
(Mobiledoc contrib here)

One thing Draft and Mobiledoc seem to have in common is a robust programmatic
API. Draft is pitched as a "framework for building rich text editors in
React". Mobiledoc pitches itself as a toolkit for building WYSIWYG editors, so
fairly similar goals.

Mobiledoc is designed to be very quick and easy to render, and additionally to
support rich content "cards" and "atoms". These are runtime-implemented rich
content sections, and our main sponsor for this work (Bustle Labs) uses them
for image sliders, animated and interactive SVG features, videos, and more.

These runtime rendering points also make it easy to have multiple
representations of a document. For example, we render Mobiledoc into text for
ElasticSearch, into HTML for normal web visitors, and into AMP HTML. When
rendering into text or AMP we can't use the normal card implementations, and
runtime-configuration makes this easy.

And the rich cards work with copy paste! and undo/redo! Anyway, there is
definitely overlap here, but IMO the goals of Draft are pretty narrow so far.

~~~
spicyj
Just so I understand fully, can you explain which things Mobiledoc handles
which Draft doesn't? It sounds like you should be able to easily implement any
of those behaviors on top of Draft.

~~~
mixonic
Hm, I don't think some of the things we're working on are easy to implement on
top of Draft, but I've only browsed the (very good) documentation so far.
Perhaps I'm wrong.

For a first, I'm not clear on how you would write a custom renderer against
the data structure (we try to do this for Mobiledoc [0], and it has helped
contributors). It seems straight ahead to derive looking at it in a debugger,
but I would love to see a link to the docs on it in case I've missed them.

As for cards, we've worked hard to make sure cursors work well around cards,
and around atoms. There aren't any demos of "Custom Block Components" [1] in
readonly mode, but based on the inability to place a cursor after a "Code
Block" with arrows when it is last, I think Mobiledoc might be a bit more
robust at this date.

But conceptually custom block components are very similar to Mobiledoc cards
[2]. Block based rich content with an object payload. We provide a non-block
construct called "atoms" that are inline as well, for things like `@mentions`
in text.

This is really neat stuff, but yup, we've been playing around with similar
ideas for a few months! Happy to see so much life in the editor world again.

[0]: [https://github.com/bustlelabs/mobiledoc-
kit/blob/master/MOBI...](https://github.com/bustlelabs/mobiledoc-
kit/blob/master/MOBILEDOC.md)

[1]: [http://facebook.github.io/draft-js/docs/advanced-topics-
bloc...](http://facebook.github.io/draft-js/docs/advanced-topics-block-
components.html#content)

[2]: [https://github.com/bustlelabs/mobiledoc-
kit/blob/master/CARD...](https://github.com/bustlelabs/mobiledoc-
kit/blob/master/CARDS.md)

[edit] looks like [http://facebook.github.io/draft-js/docs/api-reference-
data-c...](http://facebook.github.io/draft-js/docs/api-reference-data-
conversion.html#content) serializes the abstract of a Draft into something
persistable, and potentially renderable.

~~~
spicyj
Yes, it should be easy to serialize the state using convertToRaw and/or
convert it to HTML/Markdown/etc. I could imagine official helpers for this
might be added.

You can try the embedded photo experience in Facebook Notes at
[https://www.facebook.com/notes](https://www.facebook.com/notes). I think it
does essentially everything that you have described. (I believe we do keep at
least one (possibly empty) block after each media object to allow putting the
cursor there.)

Mentions (like on Facebook) can be done easily with Draft's entities, and
mentions that behave more like syntax highlighting (like on Twitter) can be
easily done with decorators.

Mobiledoc looks pretty awesome though. I hadn't seen it before this -- thanks
for sharing.

------
leeoniya
Is there a specific benefit to having this built on top of React rather than
just wrapping an existing editor's API [1][2][3]? Is it cross-usability for
React-native or just NIH syndrome?

I'm not sure how I feel about re-implementing all the things and introducing a
React dependency to everything. The lock-in seems okay if React really is the
final word in UI frameworks (though it is very large and currently very slow).
I am certainly not in this camp, however.

[1] [https://github.com/neilj/Squire](https://github.com/neilj/Squire)

[2] [https://github.com/quilljs/quill](https://github.com/quilljs/quill)

[3] [https://github.com/zenoamaro/react-
quill](https://github.com/zenoamaro/react-quill)

~~~
spicyj
(Biased React dev here.)

The key insight in Draft.js is that it's incredibly difficult to keep your
model in sync with the browser's contenteditable behavior unless you intercept
many of the behaviors and perform them entirely in the model, then change the
DOM accordingly. Medium found the same thing when building their editor:

[https://medium.com/medium-eng/why-contenteditable-is-
terribl...](https://medium.com/medium-eng/why-contenteditable-is-
terrible-122d8a40e480)

In order to build high-quality text editors, you need to be in control of
what's happening in the DOM. There's obviously many ways to control the DOM.
React is a solid base for this, as are many other libraries. Facebook uses
React extensively so it made sense to use as a base for Draft to avoid needing
to essentially rewrite React and to make it even easier to integrate with
existing React apps. Of course, you can also use Draft easily inside a non-
React app.

The entire Draft model is also separate code decoupled from the UI and you're
free to use the model and implement the views yourself if you're allergic to
React or aren't targeting the DOM. The Facebook Groups app uses Draft's model
but implements custom views for it in React Native.

~~~
almost
Any chance that react native view code will be released at any point? Would be
so useful!

~~~
spicyj
Good idea. It's based off of an older version of the Draft code so it might
not work out of the box. If we don't get a chance, hopefully it won't be hard
for people to build out a solid implementation on RN.

------
iandanforth
Neat, but. I once had to do extensive testing of a rich text editor and know
where the most bugs were? un-ordered lists. The world has been trained to
expect a very specific set of behavior from bulleted lists by MS Word and it's
really tricky to emulate. Specifically, how do tab and shift-tab modify the
list? If you have an indented bullet, and hit return from the end of the line,
what happens? What if the previous line was bold? What if I select most of two
lines and hit delete?

Their demo falls far short of expected functionality which makes me think that
there is a huge amount of work to go from this library to a working editor.

~~~
sime
The docs discuss lists and reference Facebook Notes which uses Draft. The demo
doesn't support the nested lists but Notes does. I've tried it out and it
supports tab and shift-tab. The only limitation seems to be that you can't
select multiple items and indent them together - it has to be one at a time.
I'm unsure if that's a limitation of Draft though.

~~~
spicyj
The default behavior for tab is defined here:

[https://github.com/facebook/draft-
js/blob/f5e6cf50558f5797b0...](https://github.com/facebook/draft-
js/blob/f5e6cf50558f5797b079db80fcda706664c74e14/src/model/modifier/RichTextEditorUtil.js#L229)

It would be easy to override it in your own component or send a PR upstream to
make it adjust multiple blocks at once.

------
amelius
Some bugs found after quick testing:

\- When adding a long paragraph, and hitting enter in between, the caret
disappears from the screen.

\- When typing some text, say "abc", followed by a large number of spaces, and
then selecting everything, the selection extends past the width of the editor
window (colored selection bar sticks out).

\- In a long paragraph, changing to a code-block, again the caret disappears.

More seriously:

\- In a paragraph of 10,000 words, the editor becomes really slow, even when
just typing text. This is strange because such operations (i.e., typing) are
local, and React is supposed to deal only with incremental changes. I'm
wondering what is going on here.

~~~
true_religion
> In a paragraph of 10,000 words, the editor becomes really slow

I think it's because typing a single character causes it to reparse the entire
typed text in order to check if the document model needs updating.

I've seen something similar in other editors. The only solution I can naively
think of is to chunk the document and only do checks within the chunk.

------
tiglionabbit
Oh hey, this looks a lot like something I was working on.

[https://github.com/nickretallack/richer](https://github.com/nickretallack/richer)

React makes it easy to do a stateless transformation from your data model to
some output, so you can model things the way you want to: as a series of
overlays onto the text.

My project uses the Google Drive Realtime API as its data model, so you can
collaborate on the text too. Or use the in-memory version to edit alone.

I never finished this thing. Was hoping to use it on a project at work, but
got shot down. Emulating cursor movements without a text area was the
fiddliest part. But I got pretty far into it as a proof of concept at least. I
was impressed at how fast it was despite being a JavaScript emulation of
content editable.

~~~
smrtinsert
I've been targeting Google Drive as well for various document options. It's
basically a free cms.

~~~
tiglionabbit
Yeah, it's pretty neat. Though it doesn't really have the performance
guarantees of a real CMS. Also I wish I could do some sort of server-side
validation like you can in FireBase. Considering FireBase now has a rich text
editor example with operational transformations, it may be the better call
now.

------
simonw
Has anyone figured out how to get a string of HTML out of this? I tried
bouncing around with the $r object in the Chrome devtools console on
[http://facebook.github.io/draft-js/](http://facebook.github.io/draft-js/) but
couldn't work out how I would return a string of HTML suitable for persisting
to a server.

~~~
palmdeezy
You need to write a parser to translate ContentState into markup. See
[http://facebook.github.io/draft-js/docs/api-reference-
data-c...](http://facebook.github.io/draft-js/docs/api-reference-data-
conversion.html#content)

------
jstejada
This is really awesome-- At Nylas we've /also/ been building one for the past
year to use in our email composer inside N1
([https://githbub.com/nylas/n1](https://githbub.com/nylas/n1)), with the
additional constraint that it needs to support extension by third party
plugins.

Building a nice declarative editing interface around an inherently mutable
structure with an imperative API like the DOM (which can mutate state from
under you, like focus) is a real challenge. _Props_ to the team at facebook
for this.

------
mhodgson
Looks like a nice entrant to the space. React is very well suited to this
problem space and they clearly understand many of the pitfalls and problems.

A few questions/concerns:

1\. It doesn't look like the undo/redo state is global to the page. The built
in undo/redo stack in browsers is global to the page so this is the
expectation users will have. If you use multiple instances of Draft.js in your
page they will each have their own stack, which is less than ideal. I realize
having a singleton to manage this across all editor instances is more
difficult in the React/Flux paradigm, but it would be much better from a user
experience perspective. Related to this:

2\. I don't think you can nest Draft.js instances. There are a number of
simple cases where you might want to do this (e.g. custom block with image +
caption). To support this in the future it seems you would need to account for
it in the selection and undo/redo stack state handling.

3\. The data format has a lot of repetition in how it stores inline styles[1].
I'm interested to know why they chose to represent the data this way instead
of using indices. For instance, you can represent a inline bold style with a
json object like so: {type: 'BOLD', startOffset: 5, endOffset: 10}. The format
they chose to use is easier to render directly, but more difficult to parse
visually and less space efficient (except in the case of styles that only
cover a few characters).

Finally, it seems most modern WYSIWYG editors mentioned in the comments here
were at least partially influenced by the original Medium post "Why
ContentEditable is Terrible"[2]. It would be great for the community to
standardize on a data model/format that could be used in all of these editors.
There are enough commonalities (blocks, elements, etc.) that I believe we
could create a common document spec that would be usable in all of these
popular editors. The benefit of this would be having a common spec to build
additional libraries for diffing, server rendering, native mobile editing, and
so on.

[1] [http://facebook.github.io/draft-js/docs/advanced-topics-
inli...](http://facebook.github.io/draft-js/docs/advanced-topics-inline-
styles.html#model) [2] [https://medium.com/medium-eng/why-contenteditable-is-
terribl...](https://medium.com/medium-eng/why-contenteditable-is-
terrible-122d8a40e480#.sbk9m56cs)

------
pfooti
This looks pretty neat, although I'm leery of the react.js dependencies as I
don't do a lot of react development. I'm sure I could wrap it up or something
if needs be. There's a lot to be said for this new move in third-generation
rich text editors to move away from relying on contenteditable and the DOM as
the source of state. A lot of different projects are doing this becuase
contenteditable is clearly not a great solution.

Still, am I missing any kind of delta event emitter? I'd like to be able to
hook edit events and push operational transform content over the wire to
support collaborative editing. Other projects like ProseMirror, Quill.js and
maybe Mobiledoc support this (I haven't used mobiledoc yet, but it looks like
that's going to be supported Soon).

------
nthnb
I've tried to work with a number of WYSIWYG editors and they always get you
part of the way before becoming a real pain. No one seems to do a very good
job planning them out and maintaining them. I, for one, am really happy to see
Facebook release something. Knowing Isaac I suspect this is some work related
to Facebook Notes which is cool because it means they're using it in the wild.

------
hokkos
Great but no support for tables, I can't use it for now :(

So I use CKEditor because it support everything the client want but it is like
a trade with the devil. It is the worst js lib I ever had the displeasure to
use, it made one developer never want to be on my project again. I needed to
fix its sources, and have the non uglyfied code load in my app to debug it,
because they only distribute working minimised merged js, I had to make the
full sources load in webpack : pack all the js and load de dependancies in
order following a config js file. The code is full of ridiculous timeout
making the code unfollowable. Never use CKEditor !

I will gladly switch once it support tables.

~~~
fredck
We really hope to change your opinion with what's coming on CKEditor [1] later
this year ;)

[1]: [https://medium.com/content-uneditable/ckeditor-5-the-
future-...](https://medium.com/content-uneditable/ckeditor-5-the-future-of-
rich-text-editing-2b9300f9df2c)

~~~
hokkos
This absolutely looks great, the Web needs a feature rich "rich" text editor,
with modern code, document model and ui separated from the core.

A quick look at the code shows you use standard import/export, configurable
import style for the ui part and this is great news. Good job :)

------
fredck
It's curious to see that many pet projects are going public at the same time,
all having the same goal of bringing control over the contenteditable madness
through a custom data model.

We at CKEditor are going in that exact same direction [1]. We are making a
strong switch to the project, wishing to make it a powerful editing framework,
just like Draft.js but in a larger scale.

[1]: [https://medium.com/content-uneditable/ckeditor-5-the-
future-...](https://medium.com/content-uneditable/ckeditor-5-the-future-of-
rich-text-editing-2b9300f9df2c#.vnr2mb8zg)

------
swah
By the way, did Facebook ever wrote why they only allow plain text? Its easy
to imagine but I wonder if they ever A/B tested it.

~~~
harel
Remember MySpace? That's why. When they allow styling of the content by users,
it turns into a style war and horrible horrendous terribly bad user experience

------
brianorwhatever
I was just about to roll my own. Thanks fb!

------
thewhitetulip
Does it support github flavoured markdown? Or can we make it support it?

------
HappyTypist
Bugged on Firefox for Android - typing overwrites what you typed before.

------
amelius
Any ideas on how they implemented this using React?

~~~
dan15
It's open source, take a look at the source code? :D

~~~
amelius
I was just curious about how they are using immutable data structures to
implement an editor. I skimmed through the code, but it is too difficult to
read that quickly.

------
ejo3
This is very nice and minimal. It's not working well on mobile though. I
wonder if they are planning on working on that.

~~~
ejo3
Correction: It works great on mobile. My mistake.

------
nanoojaboo
How does it compare to Trix by Basecamp?

------
cdnsteve
<3

------
dustinpkane
Man that is beautiful

------
Numberwang
Seems good. I would have loved a few more features though.

~~~
shorodei
It's a framework. You build what you want on top of it.

------
fiatjaf
Anything done by Facebook gets infinite upvotes nowadays.

~~~
terda12
Except their mobile app. Anything made by their mobile team should not be on
anyone's phone, battery drain is a huge problem.

~~~
rco8786
Literally one of the most downloaded apps of all time.

