ProseMirror 1.0
marijnhaverbeke.nl
marijnhaverbeke.nl
Some of the things we've found really great about working with ProseMirror:
- Separation of the data model from the rendered display has allowed us to extract things like tracked changes and comments which we traditionally embedded as HTML tags in TinyMCE. This leads to less cleaning and prevents inadvertent publishing of metadata.
- Unidirectional data flow makes it work well with applications that use this type of data architecture.
- Separation of modules (prosemirror-state, prosemirror-model, etc) has allowed us to quickly write better tests around our editor code.
- Decorations have been great for implementing the previously mentioned metadata aspects of our editor like comments and change tracking. They're useful for features like our custom spell checking implementation, which checks for Times style in addition to normal spelling/grammar.
- Node views allow us to implement rendering in our own way. We've been rendering React components into them which will eventually allow us to share code between our editing environment and our user facing web stack. They also allow use to render the same editor schema in different ways depending on the context/view they are being used in.
- The step/transaction model has allowed us to move from what was previously a set of additions and deletions persisted within the document to a calculated change tracking implementation. This allows both for a cleaner document but also allows for a wider range of tracking (i.e. show the differences between versions 10 and 15) rather than a static current vs the last "accepted" version comparison.
- Prosemirror’s plugin system is really simple and flexible and has allowed us to add new features to our editor rapidly in a modular way without interfering with other features (comments, custom spell checking, custom find/replace, etc).
When you were surveying the editor-landscape, what made you choose ProseMirror over its competitors?
More pertinently, I’m interested in what made them choose ProseMirror at the time, as opposed to what they like about it now.
About 6 months in, near the start of 2016, when moving on from the exploration/demo stage of the project to actually building out the real deal we took another look at the landscape and decided to move to ProseMirror. I don't remember the exact points that went into the decision but transitioning from our in house solution to ProseMirror felt pretty natural as they followed similar design philosophies.
You went down the hard path of rolling out your own editor, and used the knowledge gained to choose a worthy successor.
I'm impressed. I should give ProseMirror another shot.
It will be Wikipages.
A visual editor for a wikipage is the crystallization of the semantic-content conflict as described eloquently by https://en.wikipedia.org/wiki/WYSIWYM
To date, despite a stream of donations and years of development, Wikimedia has failed to develop an editor that is better, by productivity and other lagging metrics, than just editing a text-field:
https://en.wikipedia.org/wiki/VisualEditor https://www.theregister.co.uk/2013/09/25/wikipedia_peasants_...
Increasingly, I believe what we really need is an enhanced markup editor-- where bolded text is bolded text, a quote is automatically highlighted as a quote, but links look like (check this link out)[http://example.com]. The ideal would be to forgo the "drop down to normal text editor" button and have the only & best way to edit be through the new editor.
Can these WikiPages be made public to non team users? I.e., made public?
This is likely a non-issue for your product, seeing as it is team-oriented rather than community-oriented.
It could be interesting though to expand Nuclino for the use in communities in the future as a lot of requirements overlap.
Our goal was to create an editor intuitive enough to be accessible to the tech-unsavvy, while also curing the ills (slowness, plugin overload) that frustrate our tech colleagues who use current enterprise wiki products.
You’ve clearly put a lot of thought into what makes a great editor — any comments you have on Wikiful's editor would be much appreciated.
I haven't released a product using this yet (although I hope to) but I really want to congratulate you for writing something that focuses on a narrow yet hard problem, that a lot of folks would consider uninteresting because it's been "solved" in other domains, and just doing a really, really good job.
I haven't tried ProseMirror yet, but I'm pretty sure that the same level of quality is there.
Thanks for your work!
Quick note: the Markdown example page (http://prosemirror.net/examples/markdown/) has a javascript error that's keeping the editor from loading.
Thanks for all your hard work.
ProseMirror was up there from recommendations from a colleague who has worked with CodeMirror as a basis for a collaborative editor before, but it needs more work for basic features.
I've tried a lot to get it working for https://github.com/fiatjaf/coisas and only managed to make it work by copying running code from one of the demos, ignoring all customization and working myself around the editor to provide the custom functions I needed.
I may be totally wrong here, but I'm trying to be sincere about my experience.
> If you're looking for a simple drop-in rich text editor component, ProseMirror is probably not what you need. (We do hope that such components will be built on top of it.) The library is optimized for demanding, highly-integrated use cases, at the cost of simplicity.
A lot of the underlying ideas are similar between Quill and ProseMirror, so I'm curious to hear a knowledgable comparison of the two. But the excellent Quill documentation, as well as the responsiveness of the primary developer to github issues and stackoverflow questions, made it an easy choice for me.
I ended up scrapping it entirely for Quill and it was a massive relief.
In my opinion as a mostly-uneducated observer to this project, it is exactly the kind of project that would benefit massively from static type-checking. I can't count the number of times things broke on an upgrade because of simple bugs in the code where `undefined` would trickle through function calls or function interfaces were updated and other parts of the codebase were not updated in accordance. These are not hard problems to solve, but if you're dogmatic about using vanilla JS with as little build step as possible, you're going to run into these all the time.
What do you feel like you learned when working on this project? Will any of it make it back to Codemirror?
[1]: https://discuss.prosemirror.net/t/discussion-the-limits-of-a...
Quill can be used for the get going quickly drop in use case. Prosemirror specifically warns against this: “If you're looking for a simple drop-in rich text editor component, ProseMirror is probably not what you need. (We do hope that such components will be built on top of it.) The library is optimized for demanding, highly-integrated use cases, at the cost of simplicity.”
Prosemirror’s schema, as documented, is more flexible than Quill’s. Prosemirror appears to allow anything, whereas Quill imposes some constraints. For example Quill requires all nodes to either be a leaf and cannot have children or a container and must at least one child. There cannot be a node that can optionally have children as is allowed in Prosemirror. In my experience the constraints Quill imposes lead to a more consistent and bug free experience across browsers. I will be curious to try out the edge cases I have encountered at this new 1.0 Prosemirror to see if it handles them the way an end user typist would expect. If Quill can benefit from a shift in the flexibility in its schema, it will do so.
Quill is far more battle tested. Slack, Salesforce, LinkedIn, Intuit and many others are using Quill in their main user-facing production products, not an internal employee only tool. Prosemirror has a great start with the NY Times but there is a large difference in adoption at the moment.
Sure. I think it's fair to say that ProseMirror is a more ambitious project, reaching for features that aren't part of (even the new crop of) existing libraries.
* Firstly, the schema feature. ProseMirror's content expressions [1] are a regular language that can be used to describe a sequence of child nodes. The editor will make sure the content of the node always matches this expression. This allows significantly more interesting things than Quill's array of allowed children—i.e. "heading block* section*" to say that a given node must first contain a heading, then any number of blocks (say, paragraph, list, figure, aside, etc), then any number of subsections. (HN's half assed markup doesn't seem to allow escapes on asterisks, so I used *'s)
* Quill uses imperative data structures and events throughout. I've really become convinced of the power of functional Redux-style architectures for this kind of component—I've found it makes it much easier to write bullet-proof extensions. (This may be a matter of taste.)
* Table support doesn't appear to exist in Quill yet. A table module with features like colspan/rowspan and cell selections has been written as a relatively small plugin [2] for ProseMirror.
* Exposing all the system interals (and designing them in a way that makes them usable), rather than hiding stuff behind a small API, means that people can do really advanced things as extensions. This was a lot of work, and wasn't initially planned, but the kind of users we're aiming for require it.
* As for real-world use, yeah, we've just released 1.0, your project is older. Still, our users (including Atlassian, which has already rolled out ProseMirror in user-facing products) have been doing very advanced stuff already, and my ten years of experience with CodeMirror mean that I more or less know what I'm going to run into.
[1]: http://prosemirror.net/docs/guide/#schema.content_expression... [2]: https://github.com/prosemirror/prosemirror-tables
(Also your website claims, wrt to ProseMirror: "Quill’s architecture is more modular, allowing for easier customization of internals. Core modules that handle basic functionality like copy/paste and undo/redo can be swapped out in Quill." I think that's a mischaracterization.)
Your points are fundamentally correct, and I would argue that your parent is attempting to limit the potential of ProseMirror, in order to preserve the need for Quill.
indeed, there will be demand for more/different products even after both of these competitors maximize their reach.
There use to be loads and loads of JS frameworks of dubious merit and with equally dubious developers. Now there's generally an agreed upon few (Angular 2.0, React, Vue) that are pretty solid and seem to be helmed by mostly sensible people.
Unfortunately, we're still in the early stages of open-source WYSWIG/WYSWIM;. By the later stages, I hope we can thin out the technically unsound editors with insecure authors.
The developers are passive-aggressive to the notion of rendering Quill content outside of the Quill Editor, having ripped out the APIs to do so from newer versions, and silencing conversations in their Github Issues.
You can see the latest flare-ups here: https://github.com/quilljs/quill/issues/993
The project also has secondary smells such as inventing weird names for existing concepts; 'Delta', for example instead of 'data source' or something more intelligible.
Lastly, it markets itself as feature-complete, but has failed to implement support for something as basic as tables, which have been repeatedly requested for the past 3 years.
Personally, I would be afraid to build anything mission-critical upon it.
I have repeated many times that the removal of getHTML was because it was a passthrough function that added no additional value to Quill. You can look at the code history and the implementation of getHTML to confirm this fact. It has nothing to do with the desire to remove functionality as no functionality was removed.
I'm confused why Delta is a bad name, since the word delta means change, variation or difference and that's seems to describe what it is: a change to Quill's content. Data source on the other hand is unspecific and even misleading. Naming is hard though and other readers can find out what Deltas are here https://quilljs.com/docs/delta/ and decide for themselves.
Tables was reported as a feature request by me early in the project life because it is a known feature of Word but only years later did users indicated strong interest in it in Sept 2016. I believe in community contribution to open source so I decided to give the community a chance to build it so I wrote offered detailed implementation guidance: https://github.com/quilljs/quill/issues/117#issuecomment-244.... The fact that this user had seemingly urgent need for it and was employed by a large public company with resources also contributed to this decision. Valuable exchanges were had in the Issue and multiple users has fully implemented it for their companies to varying levels of feature richness depending on their requirements. An official canonical implementation is coming in 2.0: https://medium.com/@jhchen/the-state-of-quill-and-2-0-fb38db....
I display html content based on quill data all the time. I've done it using quill to generate the html source, by writing a separate library to convert from Delta representations to html strings, and most recently as an angular 2 webcomponent (since angular 2 doesn't really like it when you inject html strings outside of it's lifecycle, if you want the resultant DOM nodes to be angularized).
All three ways have worked well. Personally, I like this last way the most, but owing to the vagaries of angular template compilation it is difficult (or impossible) to really abstract it into a standalone library (because the top level template needs to reference any possible custom components that are local to your app, such as an atmention thing that pulls in an avatar image from some profile data or whatever)).
Anyway, I use quill, and have used it since we'll before 1.0 days. At the time, it was the only game in town for emitting Deltas that could be wired into an OT engine, and it still works really well in my concurrent rich text editor for an internal cms/forum.
One thing, how does ProseMirror work roughly? Does it avoid the `contentEditable` minefield? (I'm speaking as someone who has built a WYSIWYG editor in a past job.)
It's interesting about not being able to easily bolt on collaboration; it was not a trivial endeavor at all, but codemirror's APIs made that part exceedingly easy :)
Or, if you mean lists starting at something other than 1.--The schema used in the examples actually supports a `start` attribute on numbered lists, but the UI doesn't currently expose it.
Do you have a Patreon or other donation method on your site?