Slate – A completely customizable framework for building rich text editors
github.com
github.com
I started using this library several years ago and have eventually had to rework it using prosemirror because I just couldn't keep up with the breaking changes.
Both libraries work in very similar ways, with slate using React for its rendering layer. However Prosemirror has been v1 for quite a while and in retrospect I'd have saved myself a lot of headaches if I'd taken the above warning more seriously.
I also wholeheartedly recommend ProseMirror. It’s a bit complicated in some ways, but it works across platforms, is used in production widely at big companies despite sort of flying under the radar, and has been stable for years. If you’re looking for a fully baked React integration, TipTap[0] seems really nice, or if something minimalist then a plug for my own integration: use-prosemirror[1].
At work we need only the most basic customization (some inline spans for template vars) and we've cobbled together a Draft.JS implementation that's pretty buggy and has random runtime errors (unhandled nulls internal to the Draft.JS code).
Draft.js was another far out experience for me. I built the first attempt at my app with it, only to discover that Draft.js didn't work on Android. It was buggy on iOS, but on Android just didn't work. If you've been using Draft.js you probably remember Android support landing with the huge PR from Fabio M. Costa at GoDaddy[0], but by then I had already decided I needed to find something else. That PR actually led me to ProseMirror:
> This approach is the one used by Prosemirror (see https://github.com/ProseMirror/prosemirror-view/blob/master/...), which is the only Rich Text Editor I've tried that works well on Android. [1]
When I looked at ProseMirror, I was spooked by the apparent complexity. Tried Quill, Trix (worked great, but uncustomizable) and then went with Slate, only to have the above-mentioned experience. Remembered that comment on the PR, and redid my editor in ProseMirror, which finally was something that worked. Thank you Marijn and the ProseMirror community. It's been a journey with these editors.
[0] https://github.com/facebook/draft-js/pull/2035
[1] https://github.com/facebook/draft-js/pull/2035#issue-2613622...
After few weeks of development we ran into IE11 issues we couldn't fix and Slate devs expressed that they are not at all interested in supporting IE11 in any way, which is a fair point of course since IE11 is on its way out and supporting it is a big chore. There were some PRs that were supposed to address some of the issues, but development is kinda all over the place on Slate so we weren't confident enough to go with it and decided to switch to ProseMirror.
It hasn't been easy and ProseMirror can be complicated, but we managed to work it out and created what we needed.
Can confirm it was a bumpy ride, but it also gave back a lot. The main reasons for using Slate over Prosemirror were the almost complete API for managing and editing a block based page, and the fact that it's written in Typescript (although partial types support is a recent addition).
We still have quite a few Slate-related bugs, and the size of our extension code to cover for slate bugs/omissions or to extend the behavior in general is now many thousands of lines long, but wouldn't have chosen anything else.
We tried Prosemirror at the beginning and it was very hard to get into. We checked again when TipTap came out (which is a wrapper of Prosemirror), but all our advanced custom logics would have had to be rewritten in Prosemirror so we abandoned the idea very easily. But we support the team behind Tiptap on another open source project, Hocuspocus, which is a client/server wrapper for Yjs, a library for collaboration with a focus on text editors.
In the end, I have PTSD from Slate, but also, we couldn't have done it without it, so thanks Ian if you're reading this!
* my first comment on HN after years of lurking!
yikes, but if it's working now then just tech debt for the future.
I initially investigated using slate.js, prosemirror, and draft.js for my project https://sqwok.im but ended up writing my own parser instead, learning quite a bit about such fun api's as browser Range(), and the many pitfalls of cross-browser compatibility. It was laborious but got it to a place I'm happy with.
Congrats on Saga! It looks like something I might use and I dig the UI.
We really needed extensive text manipulation, so starting from Slate gave us a considerable initial boost, but congrats on building your own parser!
Congrats to you and if you try out Saga, let us know about it :)
Im in the middle of sizing up text editors myself, seems like editor.js would require less work, but wondering if I’m missing any red flags and should go with Slate or tiptap (prosemirror) instead.
At some point down the road I’d love to implement collaborative editing.
If you're going for a new text editor, I'd start with Tiptap and try to check how to do advanced custom stuff with Prosemirror. Maybe if Tiptap 2 was out a year ago, we would have started with that.
For collaborative editing, definitely check out https://yjs.dev
I chose Slate over Prosemirror because the source code of Slate is Typescript written in a clear modern style, and I was able to start reading any part of it and understand it easily, whereas I find Prosemirror's core source code more difficult (this may just be a reflection of my shortcomings). I spent a lot of time initially just reading Slate PR's claiming to fix bugs, then integrating the PR's into my fork, often in a way that makes sense for my project, but likely wouldn't in general (I left helpful remarks on Github).
Slate is an interesting project, and it is comparable to Prosemirror. However, development is structured very differently at present, and I think there's little funding behind Slate, whereas the author of Prosemirror seems to have done a good job encouraging sustainable donations. I think Ian Taylor, who mainly wrote Slate, also cofounded a company called Segment.io, which is a serious startup that was recently sold to Twilio, so I don't know what his motivations are.
I have no plans to switch from Slate to Prosemirror. Getting virtualized windowing to work with Slate was quite difficult, but it's really table stakes for what I plan on doing longterm, and I don't even know where to begin to do virtualized windowing in Prosemirror.
I'm still working on migrating my team's Slate implementation from 0.47 to 0.5x.. the new API is simultaneously simpler but also.. harder for me to grok? Maybe I just am having trouble with the documentation because I end up reading the source more often than not.
In my experience, I think the official documentation is just an introduction and overview, and that you have to read the source code of Slate when you're serious about doing development using it. This is not necessarily bad, since the source code is pretty readable, and the fact everybody seriously using slate is reading the source increases the number of contributors.
I can tell though that I'm going to have to write my own documentation (for my coworkers) about how to use Slate, because for me, having explicit examples of proper function usage is incredibly helpful and there isn't much of that in the documentation.. so we're basically just left with the existing examples which don't come close to covering all of the options each function has.
I'll also probably have to include a migration guide (e.g. if you used to do (a) with the old API, try (b) in the new one.. (it's probably just Editor.nodes))
I agree that Slate is nicer than ProseMirror with a more standard code style, the fact that it's not scattered among a bunch of repos, and that it's written in TypeScript. And it's not great that ProseMirror seems to have a bus factor = 1, maybe 2 or 3. That's not the case with Slate right currently, right?
It's remarkable you built cocalc with Slate. And the virtualization. Really big work.
Is it somehow that Slate is more suitable handling asynchronous data (e.g. server generated uuids for each block, recursively fetching content for each block and its children)?
Test-driven development is not my usual approach to coding, but it's extremely beneficial (and easy to do) with slate. Especially for the recursive normalizer, which has grown very complex and fragile but plays an extremely important role in my editor.
I worry about long term maintenance of the library, only a small trickle of contributions come in. But in practice its been a perfectly stable library.
RTE in the browser is a full-time job even with a library like slate. Be warned!
So after some research I picked prosemirror which is used by Confluence but prosemirror is the harder to learn and the most flexible, there was also Slate which is used by Slite but it was not as flexible as prosemirror and less robust . Notion and Google docs are using their own custom editor BTW.
If you are looking for a rich text editor, there are surprisingly a lot of ressources. Either search for "rich text editor", "slate vs prosemirror" in Google, or my preferred way to get quality information. Search "prosemirror" in the HN search and read the threads [2]
The big complain I have with prosemirror is the fact that there is no official repository of Plug-ins instead everyone is rebuilding everything
[2] https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
To be fair, both Slate and ProseMirror call themselves frameworks for building rich text editors as opposed to drag-and-drop editors themselves.
The best way to build an editor yourself then would be to look at other existing editors using the same framework, and try to understand the architecture and usage.
Is there such a thing out there?
I have tried the demo[1] and couldn't find how to switch to MarkDown code mode. In Typora I can just press Ctrl+Slash.
If you start diving deeper you’ll find out that image handling is just super complex and the behaviour is dependant on what you’re building. Then you’ll be happy to have full control about the behaviour with editors like Slate, ProseMirror or Tiptap.
Some would need uploads, others just links, then copy and pasting, alt, captions, styling, etc...
Slate makes it easy to extend its core with custom blocks. Now, it's definitely some work but it's actually very intuitive to work with.
https://plate.udecode.io/ https://github.com/udecode/slate-plugins
Similarly, there's slate-yjs for integration with yjs, and so forth.
So while editing on page, I want to click the rendered heading and be able to select text and start editing it - without necessarily being able to influence the HTML in any way. Just the text, no styling.
tldr of above: dont allow ctrl+b or pasting of styled content (and probably prohibit enter presses or pasting newlines), only plain text.
Also, if the heading is an inline element inside the h1 element, and its bunking together with other stuff (icons or whatnot), editing of the headline span only should still work.
tldr - edit an elements text inline, in fact the element may be display:inline itself
I had immense difficulty getting this to work with Quill - it wasn't customizable enough. Would Slate work?