I’m creating a rich text editor using contenteditable with Elm.
You can see the initial prototype here, although it still has a lot of bugs, especially in Safari and with selection updates after style changes. It also doesn’t have a lot of features implemented yet (for example: undo/redo, list items, drag/drop, good mobile support)
The inspiration for this project came when I created a hobby language exchange site (en.modole.io) a few years ago. Initially I wanted to write it in Elm, but when I needed to create a custom rich text editor (for correcting people’s grammar), the choices in Elm were non existent. I ended up switching to React and DraftJS at the time. I came back recently to Elm to see if this had been implemented yet, and it seems like it still hasn’t. So, I decided it would be a good open source project to start, and here we are.
I’m running into some problems with selection and dom state, and most of them revolve around these two issues:
The first is that when the Elm VirtualDOM gets out of sync with the real DOM, it throws a lot of exceptions and doesn’t find a way to resolve itself (at least when debugging). This is very common when you use contenteditable; there’s a lot of times where the browser will randomly insert a text node or element that wasn’t there before, which often triggers the Elm VirtualDOM getting out of sync with the real dom state. This in turn makes it impossible for the VirtualDOM to rerender itself if there’s an error. The way I resolve this right now is by using a mutation observer and aggresively remove nodes that don’t match the specific format that I expect, but this is very very hacky. I’m wondering if there’s a better way to resolve this, or if there’s a way to make it so the VirtualDOM is better at handling errors (or even just detecting errors so I can force a complete rerender with a keyed node) when it goes out of sync with the real DOM for whatever reason.
Anyway, I appreciate all the work that’s been done to get Elm where it is today. I’m sorry if any of this is unclear, please let me know and I’ll be glad to try to clarify anything. My next steps are to more carefully study ProseMirror and Slate to try and fix the large amount selection and input issues that I’m discovering with the current implementation. I’d appreciate any feedback people have, thanks!