I made a rich text editor in 2004 and last year I made another one, and nothing has changed. The most annoying thing is that contentEditable works different in different Browsers. Some browsers for example use <div> instead of <p>. And browsers will add extra HTML elements! If you for example pass in <table> the contentEditable will add a <thead> element, so you constantly have to check what the contentEditable is up to. It would probably be easier to use HTML Canvas and implement everything from scratch.
You might be interested in the video linked below on how DraftJS (which was the forerunner of SlateJS) uses the virtual DOM created by React along with contentEditable to make the same tooling work across browsers.