CKEditor 5: New approach to rich text editing on the web
ckeditor.com
ckeditor.com
Not only do you get to spend all day every day wading through the impossible pile of bugs, contradictions, mutually exclusive implementations and downright wackiness in the thing itself (did it seriously just allow the selection to include the opening DIV tag of the contenteditable itself???), but you get to have the same conversation every day with developers who haven't ever used ContentEditable and therefore consider it to be trivial.
"Why are you implementing the caret in javascript? Haven't you heard of ContentEditable?"
"Why is your simple WYSIWYG editor component seven megabytes of javascript? Wouldn't it be better to just use ContentEditable and be done with it?"
I only had to work with the technology for a few months. Years ago. And I'm still scarred today. Props to these guys for sticking it out!
Three words: it was hell.
The CKE people are some of the most hard working devs I've ever encountered in my life. I still find it funny how making little details like backspace/delete key behavior work is such a gargantuan task. And almost nobody gets it right.
Anyway it was a hard and thankless job, but during these almost two years I learned a lot about having an, um, work ethic and doing things to the best of my ability.
Also my current job looks really easy in comparison.
That's always the way I thought it should be done, with a separation of display and structure.
I used to work with a developer who maintained and actually made a decent chunk of change licensing out a very popular rich text editor developed before ContentEditable was even a twinkle in the browsers eyes. We used it pretty heavily within the company as well.
Knowing first hand the horrible feats of iframe content string manipulation that had to be done to make an RTE work in Netscape and IE5.5, ContentEditable seemed like a DREAM.
Ends up there's still a demo up for it, and it almost entirely still works!
http://madebymany.github.io/sir-trevor-js/example.html
(Looks like Froala also gives a block-based design in addition to their rick text editor)
As we continue to insert and embed a variety of content types into these editors, I feel like this approach is more suitable. Any thoughts?
For example, its powerful widgets system [1], which can be used to handle "blocks", providing at the same time an excellent user experience.
At the same time, it would avoid issues that we see with the current solutions or prototypes available out there. For example, paragraphs would not be treated as separate blocks, like a video embed, but instead, they would be part of the content flow. This would allow for easy selection of multiple paragraphs. This would also avoid issues with large selection copy-and-paste.
What is needed here, is work. And this work much probably would go beyond the CKEditor scope, because it needs some level of integration with the application. It needs the development of such "blocks, and control of its behavior. All this on top of a dedicated UI solution, maybe in some senses similar to what we have with Letter [2].
There are hundreds of different use cases for editors. Our intent with CKEditor was designing a decent framework for others to build on top of it. It would be great to see the community getting together to bring such solutions to life. We're more than happy to help.
[1] https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_widget... [2] https://ckeditor.com/letters/
Side note, list of various editors: https://gist.github.com/manigandham/65543a0bc2bf7006a487
The big win that you get with a block-based system (as opposed to 1 big chunk of HTML) is that it allows us to build out the content editing interface in a way that is very "guided" for the user... like, if there is a photo gallyer, we have a repeating list of slides and they have fields for a photo and a caption. Then on the front-end we can build our HTML+CSS markup around those specific fields. You can't do that easily with 1 big chunk of HTML.
I've been wondering if this wouldn't be good for something like MarkDown editors that show the output as you type side-by-side, because you would be able to limit compilation to the block being edited (in this case, to maintain document structure the blocks would have to be be defined by headers).
Although I also would expect that dedicated tools do this already for efficiency purposes.
The reason I'm thinking about this is because I once saw a product in development at an e-learning company where they showed me a new product where (among other things) they wanted the students to write their stuff in MarkDown, in a naive "re-render the whole thing on every keypress" way. This... did not really scale at all.
On a note that's tangentially related to this but more directly related to the top-level post, ProseMirror has a demo which involves a markdown-to-WYSIWYG editor where both sides are editable: http://prosemirror.net/examples/markdown/
SharePoint is knocking and asking for it's render model back. Web-parts in SharePoint are the whole reason why SharePoint runs like a dog.
For the open web to go down this route is very worrying indeed.
* Concrete5: http://www.concrete5.org/
* Craft: https://craftcms.com/features/matrix
* Wagtail: https://wagtail.io/features/streamfield/
* Kirby Builder: https://github.com/TimOetting/kirby-builder
* Lektor Flow Blocks: https://www.getlektor.com/docs/models/flow/
* ACF/FCF: https://www.advancedcustomfields.com/add-ons/flexible-conten...
* Wordpress Gutenberg: https://wordpress.org/plugins/gutenberg/
As a developer, there are 2 advantages I've found to the block-based approach:
1) The editing interface can be custom-tailored to the content and the non-technical users who are editing the site via a GUI interface can be more "guided" through the data. E.g. a photo gallery can have repeating list of slides and each slide has separate image + caption fields. This is hard to do with a single WYSIWYG editor (Worpdress uses "shortcodes", for example, but those are a terrible UI for most non-technical users... the whole point of a GUI is to not have to use code)
2) The front-end HTML+CSS markup can more easily be customized around the content fields. Using the image gallery as an example again... since each photo + caption of a slide is a discreet content field, I can insert that into any photo gallery markup I want. If the input data is itself HTML (as it would be from a WYSIWYG editor), I don't have that ability (unless I parse the HTML I guess, but that is terribly brittle and making a ton of assumptions about the generated HTML that will probably change depending on WYSIWYG widget version, where the content was pasted in from, etc).
Brilliant! Bet he built that because he couldn't cope with the insanity of ContentEditable either.
Probably not safe for Morty's to use tho.
One thing I've realized playing with a ton of different editors is that contenteditable gives you one very important feature that you can't fake yourself: access to the browser's spell check and corrections. It's possible that CKEditor ignores everything else about contenteditable, but turns it on just for red squigglies.
I covered the "Can't it be avoided?" section in this article a couple of years ago: https://medium.com/content-uneditable/contenteditable-the-go...
tl;dr: Unless browsers will open for the Web multiple crucial features (such as IME, keyboard, selection, touch, on-screen keyboard, spellchecker, etc.) contentEditable is the only sane way to handle text editing.
There's an ongoing initiative to fix this situation but it's an extremely complicated topic. I wrote a few words about it in https://medium.com/content-uneditable/fixing-contenteditable... but later things got even more tricky. Since then I've been on W3C's meeting in Paris and contributed to many discussions about the standards and I can say that this whole topic makes even the most experienced browser people suffer when trying to solve it. Fortunately, 2 years later I can still say that things move forward. E.g. the beforeinput event landed in a couple of browsers.
There is a route you can go that doesn’t use contenteditable, except as a small box at the cursor position to handle IME; it’s what Google Docs does. At my most recent job (stealth start-up) we built an editor like this, painting our own selection and everything. It makes certain things easy or possible — custom text wrapping, tab stops, custom handling of cursor and selection with regard to embeds. It doesn’t get you very far on mobile web, though.
Using those, implementing IME should be relatively easy. The events tell you which partial characters to show, and which completed characters to insert.
Listening to these events and using DOM diffing can get you a more or less accurate idea of what happened. But 'relatively easy' does not apply.
I have yet to find a free contenteditable-based WYSIWYG editor that works properly with the Korean IME in recent versions of iOS. Duplicate characters everywhere. Even the Enter key sometimes works and sometimes doesn't, depending on what character is immediately before the line break. Froala is better, thanks to a Korean guy who helped develop a fix for them despite the fact that it's not even FOSS.
As much as it is doable for standalone editing, it is a nightmare for collaborative editing, where content changes all the time - not only at the place where you type. Each content change may cause composition (IME) to break. That's how the browser works.
This is one of the reasons why "real-time collaborative editing" solutions often implement "block limiting" -- one block/paragraph can be edited only by one user at the same time.
Enabling IME will be one of the toughest goals for CKE5's collaborative editing solution - Letters: https://ckeditor.com/letters/
Seems like there's a good framework in place to catch up to the competition. I'd switch away from TinyMCE or Summernote if there was a component/widget system that worked well. Writing custom behavior for any HTML editor is painful, and none of them have a big use case in mind: custom layouts.
SiteOrigin's Page Builder for WordPress is cool: https://wordpress.org/plugins/siteorigin-panels/
I wanted something (Free or paid) like what's shown in the above video, that's independent of WordPress. Couldn't find a darn single one, if you can believe it. I'm stuck with Summernote + workarounds to get something similar for a Laravel project of mine.
I can, because I've been looking for one. I believe there's a market for well done components like this:
* Drag and drop page component builder (think Leadpages, Unbounce, SiteOrigin Panels)
* Drag and Drop email builder (a la MailChimp et al)
There's no need for every SaaS and startup to build their own - better to have a component (or even a dedicated service to integrate) to provide these JS-heavy timesinks than waste time while validating the idea creating them.Have you seen this? https://github.com/unroll-io/react-email-editor was released recently.
I got my hopes up when reading the intro that we would see a more structured output (not just the underlying in-browser data model). I would love to see a WYSIWYG output a JSON structure with markdown content.
Not to minimize what appears to be a massive and successful effort! I just feel like HTML is a completely inflexible and rigid way to save content.
However, it is understood that in the modern web era, there is a need for more. In CKE5 there is a "data processor" unit. The data processor is responsible for taking DOM (generated from editor's data model) and converting it to the output you want. The default processor is HTML processor, but you could hook there any processor that can convert DOM structure to anything you want. You can use already existing libraries or write your own if you need something really custom.
To sum up, the road from editor's model to the output data is this: custom model -> view (DOM-like structure) -> DOM -> Data processor -> stringified data
In many cases having the editor store HTML internally is the best solution, especially if the output will eventually be HTML anyway. Think of a Wordpress post submission page, or a website comment page.
Storing a paragraph where words might be bold or italic — a string of HTML’s pretty great for that, compared to some convoluted JSON thing, and can pretty easily be converted to other formats if needed.
Even a list of paragraphs with mixed occasional lists etc. HTML is still pretty friendly at that point.
I think where HTML strings outlive their usefulness is when you start mixing in <div> <iframe> <script>, nested sections. The string starts becoming unpredictable at that point and you have to worry about side effects.
But for use cases where you want a small whitelisted set of tags, I think HTML is great.
So, why did we create a Markdown data processor for CKEditor 5? (You can find a demo of it here: https://docs.ckeditor.com/ckeditor5/latest/features/markdown...) It was just to showcase that you can actually do that. But I'd never recommend it to anyone. HTML as a format is standardised and stable and there are even more tools to process it.
PS. There's the CommonMark standard, but it was created too late and its adoption is low.
PPS. We actually wrote an article called "A Standard for Rich-Text Data" – you can read it here: https://medium.com/content-uneditable/a-standard-for-rich-te...
What on Earth happened? HTML5 has pushed the web platform so far forward from where it was back then; how did this one little corner of it end up stagnating?
So sure, the new CKEditor does more or less what Quill, Slate, ProseMirror, and most other modern WYSIWYG components do—it separates its data model from the editable DOM. That's good, but not new.
3 Markdown documents, one JSON doc.
[1]: https://docs.ckeditor.com/ckeditor5/latest/examples/builds/c...
I vaguely recall that last time I poked around I found an extremely high-level algebraic breakdown that made no sense, and only after a _lot_ of digging was I able to turn up an actual example implementation that wasn't 100% useless (because contextless) theory.
I fear that understanding OT is a case of for example spending 6 months reading Etherpad.
Anyway, I believe that you can find a good entry point to OT here: http://www.codecommit.com/blog/java/understanding-and-applyi.... It gives a nice overview of the problem – in a human-readable language – but it’s only the beginning of the journey.
The original OT implementation has been designed for linear documents – texts. It does not fit very well with tree structure – you don’t want elements (tags) to intersect after resolving collision. It also does not fit undo where the order matters.
For sure, operational transformation is not a closed subject, which you can just learn. It is an open problem with many cases still unsolved. If you are looking for a good topic for a thesis, I would recommend it :)
Oh.
> A guy responsible for OT in Google Wave wrote once that he spent 5 years on it and it still does not work well in all cases. After 3 years of struggling to get it right, we know what he meant.
...Wow, I see.
(As an aside, I think it's really sad Wave's "cool" UI was never properly released.)
> Anyway, I believe that you can find a good entry point to OT here: http://www.codecommit.com/blog/java/understanding-and-applyi.... It gives a nice overview of the problem – in a human-readable language – but it’s only the beginning of the journey.
I actually think this is one of the articles I found a while back. I agree that it's very thorough and in-depth, and, uh, I've managed to get slightly further into it before I started hitting PgDn repeatedly and my eyes glazed over than when I read this a few months ago! :)
> The original OT implementation has been designed for linear documents – texts. It does not fit very well with tree structure – you don’t want elements (tags) to intersect after resolving collision. It also does not fit undo where the order matters.
Ooooooooh yowch.
> For sure, operational transformation is not a closed subject, which you can just learn. It is an open problem with many cases still unsolved. If you are looking for a good topic for a thesis, I would recommend it :)
Hah!
When I was exploring OT a few months ago I also explored alternatives such as realtime diff/match/patch into a model held in server memory. The simplest way to do this ultimately stores approximately documentSize*clientCount for every single document. That lets me keep an exact copy of every client state on the server, letting me tag updates with the hash of what the document should now look like. For small-scale projects the massive-but-not-concretely-exponential memory requirements of such an approach is somewhat out of control but not completely unmanageable: 1000 documents of 1MB each being edited by 20 clients each requires 20GB of RAM. (But my first guesstimate of sane limits - 10000 documents and 500 clients - would require 5.2TB though, haha.)
Hmm.
I just realized... some of the buffer architectures commonly used in text editors might be usable to implement server-side deduplication. Or... you could even probably just implement a copy-on-write scheme. Either would probably be an effective design win because (in the contemporary/common case) all clients editing a given document are generally seeing a 99.99%-accurate representation of that document relative to other users; if the network is good, there's only really a few characters' difference between users.
OT feels like architectural overkill at the fundamental level, but I know that's just my overwhelmedness with the mental models required and the sense of "does it really have to be this hard?". I recognize that it really is that tricky, and kudos for keeping at it and then turning around and making the result open source! :D
This article had some visibility on HN a couple weeks ago, perhaps it is what you are looking for: http://digitalfreepen.com/2017/10/06/simple-real-time-collab...
The fact that that article needs 10 plus pages to describe one of the simplest use cases belies the unfortunate underlying truth: OT (and realtime co-editing) is intractably difficult for all but the most constrained data models. Which is a pity because it is undeniably cool, and why we built Convergence (https://convergencelabs.com) -- general-purpose realtime collaboration.
One of the best overviews covering CRDTs and OTs, especially in the context of collaborative editing.
Text typed into the content editable is rendered into SVG elements. Unfortunately that doesn't allow a browser's spellcheck to work so they had to implement their own.
iCloud Notes works in a similar way but it renders to canvas elements instead of SVG. Also doesn't provide spellcheck.
Congrats, though. Seems like an ambitious three year long project that you actually pulled off!
I don't know if mobiledoc pioneered this approach of separating the data model but it was the first time I saw it and it felt right.
Glad to see so many editors do this now.
In CKEditor 5 we took perhaps the longest possible road so a tree structure with Operational Transformation support and couple of other goodies. It costed us a 3 years of work, but it was worth it. We proved the concept and validated the results by implementing the Letters app (https://ckeditor.com/letters/) which supports real-time colaborative editing for real (with selective undo, commenting, displaying selections of other users, etc.). We'll now be working on adding more features like e.g. tables support which rise the bar for the data model and the whole architecture even higher, but we're very optimistic seeing the results to far.
http://jejacks0n.github.io/mercury/
for complete wysiwyg editor list;
https://github.com/cheeaun/mooeditable/wiki/Javascript-WYSIW...
(If we're doing show and tell, my old quick and dirty prototype for a structured FAQ editor still mostly-works under Firefox http://www.googlemappers.com/dev/prototypes/faq/template.htm)
Here's the link: https://tweakers.net/plan/1385/finetunen-van-de-lay-out-en-h... ( dutch)
* We need to implement a custom user interface and CKEditor 5 makes this easy. Its modular nature enables us to build a custom "headless" bundle using Webpack. Keystroke handling is currently tied to the CKEditor 5 user interface, though, which is problematic as you don't want to reimplement what the Enter key does when editing, say, lists or block quotes. The team is actively looking into this issue, though, and it is possible to use a custom user interface while still benefiting from CKEditor's keystroke handling using a hack I documented here[1].
* The output format is (very clean) HTML. If we ever change our implementation to use another rich text editor, we don't want to write a server-side migrator moving user content from one editor format to another. Also, HTML is the output format we're looking to consume.
* Unlike most other rich text editors, CKEditor 5 will likely support pasting from Word (and possibly Excel) in the future[2]. Our end users are likely to copy content from Word and Excel (after all, we're creating "Excel for apps"). Handling this well is notoriously difficult -- here's the CKEditor 4 implementation[3]. Where TinyMCE makes this a proprietary add-on[4], CKSource will likely make this part of the open source version of CKEditor 5[5].
* When CKEditor 5 matures, CKSource will offer commercial support.
* We're interested in adding collaborative editing to our SaaS solution in the future, and CKSource's Letters project[6] demonstrates that CKEditor 5's architecture is up to the task.
* What should the HTML output of a rich text editor look like? CKSource's "Editor Recommendations" project (licensed under a Creative Commons license) spells out this in detail[7].
* CKEditor 5 is licensed under permissive open source licenses (MPL and LGPL in addition to GPL).
* CKEditor 5 has a responsive community and an active chat channel where the core developers hang out[8].
The downside to adopting CKEditor 5 at this early stage is that the project isn't fully mature yet. There's no out-of-the-box support for things like colored text and tables (though adding support for colored text through a plug-in is trivial, thanks to how the architecture works).
Also, browser support is spotty. Internet Explorer is not supported in any capacity (Internet Explorer 11 may be supported in the future[9]). While Edge is formally supported[10], we found problems that were serious enough for us to disable the editor when that browser is run. (Our SaaS application falls back to plain text editing when rich text editing is not available on account of the user's browser.) Also, only Safari 11 (released on September 19, 2017) works with the default build of CKEditor 5 due to a WebKit bug[11]. Finally, only recent versions of Firefox can be used that support the "selectionchange" event (which means Firefox 52 and later versions; Firefox 52 was released on March 7, 2017).
All in all, we're happy with our choice, but you may want to wait for the project to mature given the issues cited above.
[1] https://github.com/ckeditor/ckeditor5/issues/488
[2] https://github.com/ckeditor/ckeditor5-design/issues/172
[3] https://github.com/ckeditor/ckeditor-dev/blob/major/plugins/...
[4] https://go.tinymce.com/powerpaste/
[5] https://gitter.im/ckeditor/ckeditor5?at=59af4683c101bc4e3a94...
[6] https://ckeditor.com/letters/
[7] http://ckeditor.github.io/editor-recommendations/
[8] https://gitter.im/ckeditor/ckeditor5
[9] https://github.com/ckeditor/ckeditor5/issues/330
Froala was already mentioned, I also heard about an editor namend Trix, that also claims not to use ContentEditable.
Any experiences with that?
Yes, please W3C, Google, Mozilla, MS, Apple do something! Improve ContentEditable or create a new better standard for it!
As a matter of fact, we're involved in the W3C's Editing Task Force since the beginning. Me and Fred (the author of the blog post) were on the first meeting in Berlin back in 2014 and I've been in Paris the year after. Unfortunately, since then many meetings were held outside Europe and they were also concerned with more technical parts of the spec(s) to which it's harder for us to contribute. However, we still try to contribute as much as we can... but I have to say it's tough.
The problem is that this topic is vast and extremely complicated. Rich-text editing itself is complicated, but when you start considering all the languages (e.g. RTL mixed with LTR, IME), different types of devices and interaction models (software keyboards, block selection on touch devices), different OSes, clipboard, context menus, accessibility (!!), and what else is there, then you just want to quit.
In 2014 we believed in the contentEditable=minimal approach where contentEditable was just meant to provide an input/output layer. Even most of the browser people (all that I can remember) were positive about the idea. We were meant to get a cancellable `beforeinput` event and more reliable Selection and Range APIs. 3 years later and things moved forward (the event is available in some browsers), but so many topics are still open that it's hard to say what's the ETA for all of this.
For example, recently it turned out that IME is a bigger blocker than we thought. Android implements IME APIs in such a way which makes cancelling `beforeinput` impossible to handle on their side.
Simultaneously, there's a recurring idea to drop contentEditable completely and implement a completely new set of APIs. If you'd analyse how many APIs we're talking about you'd welcome contentEditable with open hands. I'm slowly starting accepting the fact that contentEditable needs to be replaced one day and that contentEditable=minimal approach may not be fully feasible, but I expect that we're talking here about next 10 years or more. There's no middle road here – either all the APIs are implemented and stable or contentEditable remains our only weapon.
BTW, I'd like to take this occasion to mention Johannes Wilm from Fidus Writer who's leading the Editing Task Force's work. Without him the whole thing would die sooner or later. We can all give feedback, but someone needs to lead the work and process feedback from all the involved parties.