
Slate.js: Customizeable rich text library inspired by Draft.js - malloryerik
https://docs.slatejs.org/
======
iEchoic
Ooh, this looks very promising. Nice work.

I'm using draft.js in production (at
[http://www.guilded.gg](http://www.guilded.gg)). I just started looking for a
replacement for a few reasons:

1\. Draft is pretty broken on Android, despite being marketed as a cross-
platform project. The team says that they're not working on fixing it, and
it's not trivial to fix. This is a dealbreaker on its own.

2\. I've had users encounter bugs where the Draft editor will serialize state
that it can't read - so you can save something, and then cannot reload it. It
appears to happen when doing some weird combination of adding and deleting
block elements. This is a dangerous and frustrating bug.

3\. In my opinion, the DraftJS API is difficult to use and extend.

Do you (@author) plan to support Android and iOS? If so, I'll definitely give
this a shot.

~~~
kiejo
Have a look at ProseMirror ([http://prosemirror.net](http://prosemirror.net)).
It works quite well on Android and iOS and the maintainer is super responsive
and has already fixed a lot of Android/iOS specific issues.

Edit: The landing page of the project does not seem to be optimized well for
mobile. When on mobile, make sure to try the editor on
[http://prosemirror.net/examples/basic](http://prosemirror.net/examples/basic)
instead, as the landing page causes some unwanted scrolling for me on mobile.

~~~
scottmf
In what way is Draft broken on Android?

Edit: I see now. I've had a look around and this open pr seems to fix it for
draftjs:

[https://github.com/facebook/draft-
js/pull/1013](https://github.com/facebook/draft-js/pull/1013)

How are you currently handling Android? We're launching with draftjs in two
weeks and need to support Android.

~~~
karn09
On Android there is a high chance your text won't appear, or the keyboard will
disappear. Trying to delete text will cause the cursor to jump around if you
hold delete down instead of one character at a time. Very frustrating.

~~~
52-6F-62
The cursor and atomic block deletion issues occur on desktop as well. I filed
an issue recently on this very thing.

It seems to be a continuation of the issues with the editor state and DOM
falling out of sync.

I can't share the implementation project, but this is the issue:
[https://github.com/facebook/draft-
js/issues/1089](https://github.com/facebook/draft-js/issues/1089) And the
component: [https://robert-fairley.github.io/draftjs-litho-
editor/](https://robert-fairley.github.io/draftjs-litho-editor/)

(my component was never meant for mobile use, though. Built for a desktop web
app.)

------
tbsthl
I am using Slate for a few months now. Before that we used Quilljs and looked
also at other editors before switching to Slate.

Slate helps me so much to speed up development. I don't want even to think
about working on my wiki app without using Slate. Sure it is still in beta.
Nevertheless it is incredible how fast ianstormtaylor reacts to bugs. I
haven't found an issue with Slate that couldn't get fixed within a few days.

Great work! Thx so much ianstormtaylor!

------
rgrove
Slate is really fantastic.

I tried it out after becoming frustrated with Draft.js, and it's been a joy to
work with. Slate's documentation is excellent, the code is well structured and
easy to read, and I love how painless it is to implement custom node types and
serializers.

------
Ronsenshi
Seems fairly similar to Daft.js including one of the issues that stopped me
from using Draft.js - lack of ability to stylize root Nodes specifically
inability to add "text-align" style to paragraphs. Sure, there are some
workarounds for that, but those are just terrible hacks bolted on top of the
inflexible model system. I had to switch to ProseMirror where that was easier
to implement.

Another thing that irritated me a lot about Draft.js is the fact that Entities
can't be applied to the same character in content block. One more reason I had
to switch to ProseMirror.

~~~
ianstormtaylor
Hey, Slate author here. I didn't realize this was going to get submitted to
HN, Slate's still in beta but it's fairly production-ready.

You actually can handle things like "text-align", by adding custom data to
nodes, which you can then read back via:

    
    
        const alignment = node.data.get('alignment')
    

Where .get(key) can be anything you want.

So text alignment would just be deciding on a key/value to use, and then
toggling styles in your React component based on the alignment value.

That said, it doesn't handle text alignment "out of the box" if that's what
you mean. It doesn't really handle anything out of the box, because you have
to opt-in to anything that changes your schema. This is by design though, and
it makes it a lot less complicated to use Slate than some of the other
frameworks when you start building complex editors. But if you're looking for
a drop-in editor that has basic features then Slate is not the right choice.

~~~
Ronsenshi
It's been several months since I used Draft, but if I remember correctly some
of the editors based on Draft use same approach with defining custom data on
the node and then applying custom class with assignment (for example you end
up with: `<p class="align-right">Text Text Text</p>`). Too hacky for me. I
would have loved if Nodes had native style suppord. Kind of like a Mark but
applied to the whole root node instead of character ranges.

> it doesn't handle text alignment "out of the box"

That's quite alright. ProseMirror doesn't handle that out of the box too. A
lot of new frameworks for rich editors surprisingly don't have that.

~~~
ianstormtaylor
You can actually choose to use styles instead of classes fairly easily too.
Since it's all defined in your custom React component you can do whatever you
want, for example it would be written as....:

    
    
        function MyNodeComponent(props) {
          const { node } = props
          const textAlign = node.get('text_align')
          return <div style={{ textAlign }} {...props.attributes}>{props.children}</div>
        }
    

Does that work for you? I'd be curious to hear what you mean by "marks but for
nodes" and how you were thinking the API would look—sounds interesting!

Slate is different than Draft in that it gives you full control over the
rendering logic—one of the things that frustrated me when using Draft and that
I wanted to solve when creating Slate. It's much more flexible than Draft in
that sense.

~~~
Ronsenshi
That does indeed work. You do need to override Node component and if you want
to have even more changes - all of those would have to be located within that
custom component.

I haven't really thought much about API or possible implementation for Marks
for Nodes. My thoughts generally revolve around the idea that blocks should
have extensible styling via Schema in the same way you can add custom Marks in
your Schema. You should be able to change styling of the nodes within the
Schema instead of overriding block simply because of the alignment or some
other minor style.

~~~
ianstormtaylor
That makes sense. And you can do that with Slate!

Since the components are all React components you can use the same types of
extending patterns you'd use in React. In this case you'd probably use a
higher-order component (HOC) that handles adding to the `style` property based
on the node's data. And then you could wrap all of your other blocks with
it...

    
    
        quote_block: alignment(QuoteBlock),
        code_block: alignment(CodeBlock),
        ...
    

One of the things I started with was making sure that components are just
React components, so that all of the patterns that the React ecosystem brings
can be used with Slate.

------
amelius
I just tried the example, and two things I noticed:

1\. The scroll region does not follow the cursor.

2\. I tried copy+pasting the demo-content a couple of times, and I noticed
that the editor gets _really_ slow at relatively small document sizes.
Especially "paste" is slow.

------
spankalee
I wish these libraries didn't invent their own document model when we already
have HTML. Just let me edit HTML, within constraints setup by a schema, and
allow extensibility of the document via HTML custom elements.

~~~
pfooti
As other people mention, you can't really do this effectively via
contenteditable, as user-intent (make that line bold) isn't uniformly
transformed into consistent DOM across browsers. Medium had a great post about
all that a couple years back. They wouldn't go through the trouble of re-
implementing contenteditable if it weren't absolutely necessary.

There are other problems with using contenteditable as well. Copy paste
becomes very challenging (you're sanitizing an dom tree and actively snipping
stuff you don't want, instead of converting only things you do want into the
intermediate representation). As an exercise, look at what an older tinyMCE
editbox actually looks like on the inside after you paste something from
MSWord.

I have been using quill.js in production for a while now (since well before it
was 1.0), and having an internal representation of the text state that gets
turned into HTML on the fly as necessary is a _good thing_. Since rich text
editors are by necessity generating user content, I feel less worried about
exposing crappy content on the DOM to people who view what was edited - I have
total control over what DOM nodes get emitted (the legacy system I replaced
allowed for pasting raw HTML, so I'm a little sensitive to this).

Plus, having my content be in an intermediate JSON representation is quite
useful. For example: It's trivially easy to wire the source of diffs from
quill into a log server for playback, so you can handle concurrent editing
without an impossible amount of work. Also, I actually transform the
representation differently depending on context. In an email notification, an
atMention custom element gets rendered as a boring href with some style, but
internally to the site, an atMention gets some custom element stuff that
allows a flyover to show the user. This would be a lot harder if I didn't have
control over the json -> html transformation at render time.

~~~
spankalee
Who said anything about contenteditable or not having control over the
content? The editor can have complete control and still store the document in
markup rather than JSON.

HTML offers a number of advantages over a custom json-based document module,
not the least of which is interop. You'd never want to store Skates data model
in a database in case you switch editors.

~~~
pfooti
I agree that HTML format has some strengths, but if you're working with data
in javascript, there's a lot of strengths to a json format as well.
Personally, I _do_ store json data in my database (in a jsonb postgres column,
which gives me some query capabilities that aren't necessarily available
operating on html strings in the database).

I also agree, though, that this leads to some degree of lock-in. You'd have to
write a transformer to convert to your new framework, but that's not
particularly hard.

Ultimately, though, the way I think about it is: react, angular, ember, vue
all work by converting a JSON representation of state into a dom tree. So, an
editor doesn't really need to be much different, as long as render times are
fast, having an internal representation that's projected on to the DOM is a
pretty common pattern.

------
thewhitetulip
Anyone wanting to look at Github, this is the link
[https://github.com/ianstormtaylor/slate](https://github.com/ianstormtaylor/slate)

------
ryanmarsh
Wow this looks really great. I've been building something with Draft.js +
plugins and I can already see how this will make my vision easier to
implement.

------
mbrookes
Two probably dumb questions, but I can't tell from looking at the examples and
a brief scan of the docs:

1) Can this be used as as content-editable substitute? 2) What format is the
marked-up text stored in, and does it require Slate to be rendered?

~~~
ianstormtaylor
Not dumb! (Author here.)

1) It depends on what you mean by substitute. It's kind of like a
contenteditable that's been implemented with React components and an
Immutable.js data model. It's not a drop-in replacement for contenteditable,
since the APIs are different. But that is essentially what it lets you do.

2) The data is stored internally in an Immutable.js tree data model. You can
convert it to JSON with the built-in `Raw` serializer. And you can define a
schema with the `Html` serializer to convert it to HTML, which then you could
render anywhere you want. I do this for one of my projects.

~~~
amelius
Does slate.js use contenteditable as an underlying primitive?

~~~
mbrookes
Yes. (That much I figured out). :-)

~~~
amelius
Thanks. Do you know why? If I had to write a text editor, I would not build it
on top of something as unreliable (across browsers) as contenteditable. But
I'm sure there is a good reason for it.

------
anotheryou
Yay, inline markdown with applied styles. I'm missing that from most markdown
editors. Sadly missing images and no real html output that I could apply my
css on.

------
ai_ia
I plan to use slate or draft to write MathJAX or ASCIIMaths writing. Can
anyone suggest which one will be more better to write MathJAX or ASCIIMaths?

------
pypetey
How hard (or easy) is it to implement mentions?

~~~
scottmf
Looks like this plugin will help [https://www.npmjs.com/package/slate-
suggestions](https://www.npmjs.com/package/slate-suggestions)

------
roryisok
The author mentions issues with a lot of editors he's not actually used, which
I find a bit odd.

Still, I'm keen to give it a go.

~~~
ianstormtaylor
Agreed! (Author here.)

I had originally started with just the few I'd used or researched in the
initial stages. But folks opened issues in Slate asking for more comparisons,
so I tacked on other libraries that people were interested in comparing. But I
should really move those other libraries to another page in the docs somewhere
with a better disclaimer.

------
scottmf
How is the performance when rendering many read-only copies, e.g. for
comments? I believe draftjs is quite poor.

------
bigtones
I get a 404 error for all of the examples.

~~~
ianstormtaylor
Ah sorry about that. I'm the author of Slate, but I didn't submit this story
or else I probably would have linked to the GitHub page itself. Fixing now!

~~~
malloryerik
Ah, I submitted this, late last night (in my timezone), because I was happy to
have stumbled across it on my quest for a highly-flexible rich text editor in
React. Maybe I should have contacted you first. I linked to the docs because
they're so clear and well made, and thought that might have been overlooked if
I'd linked to slatejs.org. Hacker News search told me that the GitHub repo had
been submitted twice in the past, with no results. Waking up I see that I even
misspelled customizable... Sorry about that ^_^

~~~
ianstormtaylor
No worries!! I should have fixed the intro docs page haha. I'm glad you like
it and thanks for submitting!

------
smaili
Slightly off topic but does anyone happen to know if GitHub's markdown editor
is open source?

~~~
gabrielcsapo
I have been looking around for awhile for it. I found something that is
inspired and looks pretty accurate.

[1] [http://code.weflex.org/markdown-editor-
flavored/](http://code.weflex.org/markdown-editor-flavored/) [2]
[https://www.npmjs.com/package/markdown-editor-
flavored](https://www.npmjs.com/package/markdown-editor-flavored)

------
sdflaj
For people that don't know React. You got documentation in plain old js?

------
marknote
All the example links broken, and show 404 not found

------
usaphp
I hate when pages break the back button on mobile

