top | item 10410879

Trix: A rich text editor for everyday writing

510 points| kqdreger | 10 years ago |github.com

130 comments

order
[+] nmjenkins|10 years ago|reply
Looks decent. The approach taken is the right one: we do something very similar with the Squire rich text editor (https://github.com/neilj/Squire) which I wrote for FastMail's webmail. Basically the browser can't be trusted to do any formatting itself, which is a slightly depressing state of affairs, especially as there has been zero improvements in this area for the last 5 years. I guess it's not shiny enough for browser devs to focus on.

Looking through the code, a few things jumped out that should be looked at:

* Native TreeWalker implementations are buggy in some browsers. In the end we decided it was safer to just implement the bit we needed ourselves (see comment at top of https://github.com/neilj/Squire/blob/master/source/TreeWalke...).

* The HTML sanitisation using document.implementation doesn't account for DOM clobbering so is currently bypassable with the right malicious content. I recommend using https://github.com/cure53/DOMPurify for this rather than writing your own. It's tricky to get all the edge cases right, so better to use something that's been reviewed by several people (and in DOMPurify's case also undergone a formal security review). Again, we use this at FastMail as part of our webmail.

[+] danso|10 years ago|reply
Nice to see this particular bit of info high up in the README (though "as seen in Basecamp 3" would fit well in the Github repo description line):

> Trix is an open-source project from Basecamp, the creators of Ruby on Rails. Millions of people trust their text to Basecamp, and we built Trix to give them the best possible editing experience. See Trix in action in the all-new Basecamp 3.

Nothing gets me more interested in trying out a JavaScript library than seeing that it's used in a mainstream production product, especially a money-making/critical product by very same the company that created/maintains it...it's a bit of guarantee that the API is relatively mature/won't-go-crazy and that someone has a vested interest in keeping the library up to date with changes in the Web. That was why React was so much more appealing to me than Angular, relative to their respective public release dates...React was already in production at Instagram and parts of Facebook, whereas I don't think Angular was in any of Google's main public facing products (i.e. search, YouTube, Maps)

[+] kacperpotega|10 years ago|reply
Agree. Although I would have wished to see it in action immediately (on an example page) without having to clone it to my machine.

Edit: Nevermind, just saw the edit on the comment below :)

[+] manigandham|10 years ago|reply
Great timing, we were just looking for a new editor for our project. Since there are so many choices, here's a list of everything mentioned in this post.

Trix - https://github.com/basecamp/trix - demo here: http://trix-editor.org/ by basecamp and used in v3, handles files/images well

Squire - https://github.com/neilj/Squire - used in FastMail webmail, better for text than images

ProseMirror - http://prosemirror.net/ - not great with images

Scribe - https://github.com/guardian/scribe - by the Guardian team

CKEditor - http://ckeditor.com/ - solid and very customizable, lots of plugins, a little dated in look/feel

Quill - http://quilljs.com/

Summernote - http://summernote.org/

wysihtml - http://wysihtml.com/

Etherpad - http://etherpad.org/ - collaborative realtime editing

TinyMCE - http://www.tinymce.com/ - older editor but still good

Textbox.IO - https://textbox.io/ - new from the owners of tinymce project

Froala - https://www.froala.com/wysiwyg-editor - solid editor, newer features like drag/drop images, v2 RC3 just released

Redactor - http://imperavi.com/redactor/ - we used this in production but quality has gone down, v2 is half the functionality at 3x the price, not recommended anymore

[+] espadrine|10 years ago|reply
Since there are quality of life improvements that are often invisible at first sight, I'd like to point out a few ProseMirror hidden features:

- Typing "- " at the start of a line creates an unordered list, and typing "1. " creates an ordered list.

- Typing the '"' character correctly replaces it with the right unicode character, and you can undo that replacement by hitting backspace. The same goes with "--".

- It hints at automatic emoji insertion here: http://prosemirror.net/demo_dino.html

- Surprisingly, the keyboard shortcuts are often inconsistent across editors; ProseMirror tends to rely on widely-used shortcuts.

That said, as I mention here[0], I am most hopeful for Slack's text editor, which supports many more enhanced features -- but unfortunately doesn't seem open-source, and is currently quite buggy.

[0]: http://espadrine.tumblr.com/post/129926358821/web-editors

[+] sleepyhead|10 years ago|reply
What is the quality problem with Redactor 3?
[+] stephentmcm|10 years ago|reply
One thing this gets right that heaps of other WYSIWYG's get wrong is lists. You can create a proper multi-level list here with order and unordered lists nested inside each other correctly. This sort of stuff is actually important for creating accessible documents as things like flowcharts need a plain text version and nesting lists is a reasonable way of displaying these.
[+] VeejayRampay|10 years ago|reply
Absolutely. I do note though that headers (h1, h2, etc.) are not supported (unless there's a way to customize the format bar past what I saw in the demo). Switching from ul/ol/li to h1, h2 and back has been a MAJOR headache for us when we tried to offer text-editing features based on an older library called wysihtml5. Medium also dodges that altogether. Text editing is still extremely complicated.
[+] cben|10 years ago|reply
My litmus test for WYSIWYG lists — which Trix fails — is

  1. start a numbered list

  2. put several paragraphs...

     > including some nested block element e.g. quote

     ... inside one list item

  3. Then continue the numbered list (not from 1!)
This is something that's trivial to express in markdown, LaTeX etc but annoying to impossible with WYSIWYG where being in a list pretends to be a per-paragraph boolean property. In many WYSIWYGs you can't semantically put block-level stuff "into" a list item, only fake it by pressing Enter, cancelling numbering on the new paragraph and increasing indent to align with list item.

This makes it a nightmare to continue the list afterwards, because actually I've already closed it. Surprisingly, while many WYSIWYG editors are only ready to start a new "1. " list, they do allow me to paste the compound item into the middle of an existing list without interrupting its numbering. Sometimes there are other rituals involving liberal consumption of Shift+Enter and Backspace, dancing with text, and promising my firstborn to be contentEditable...

Anyway Trix fails it on the simpler task of multiple paragraphs in a list item. I haven't looked at the code but it seems its content model (at least strictly enforced) for list items is something like:

- a single block element (can be a quote or code) - followed by zero or more sublist items.

It's good that Trix won't let me increase indent on a paragraph that doesn't fit its content model. But I need a stronger model for my docs...

Now a quote does allow multiple block content! What happens when I put a quote inside a list and then add sub-lists inside the quote? Madness:

  1. foo
  2. | bar
     | baz (this was Enter, not Shift+Enter)
  3. | 1. sublist
  4. | 1. | ququux
     |    | multi-line/paragraph.
  5. | 1. #code () {####
     |    ###...########
     | 1. #}############
  6. | WAT?
  7. | * ulist...
  8. | * | 1. | - he he
I'd hope the continuous outer / non-continuous inner numbering is just styling bugs and not a crazy model?

P.S. A smaller usability issue: how do you make a numbered list with bullet sublist (or vice versa)? Enter->increase indent->switch to bullets works but Enter->switch to bullets leaves me with no option to increase indent. Unnecessarily confusing.

Anyway, lists are why I hate all WYSIWYG with passion as a user. I wish WYSIWYM with explicitly visible structure (cf. TeXmacs) was more popular.

[+] amelius|10 years ago|reply
What is the computational complexity of inserting a character into a text containing N characters, using this editor?
[+] riskable|10 years ago|reply
This is a very astute observation. When I was developing Gate One I experimented with something similar for terminals (using contenteditable to work around issues with keeping elements up-to-date while retaining formatting) but ultimately ran into severe performance problems. That was years ago though and browsers have gotten much better at handling contenteditable with larger amounts of text.

However, the more tags you add to contenteditable elements (i.e. for formatting) the more work the browser has to do every time there's a page reflow and there will be a reflow every time the text changes. So the more formatting, the slower (less responsive) it will be.

The workaround for this (no idea if it's used in this editor) is to divide the document up into lots of individual <div> elements with contenteditable=true and make sure that all outside-the-view elements are removed or at least hidden via 'display: none' and merely re-show them on-the-fly as the user moves about the page. Keeping a page or two above and below the view pre-rendered can help with responsiveness and you'd also have to make sure to pre-fill all the document's unseen space with whitespace so that the user can scroll to any position accurately even if the browser is still retrieving and rendering that portion of the document.

I came very close to implementing such a solution but ultimately decided on something else entirely (server-side rendering and a difference-based terminal update protocol). It's a great idea for an editor and tows the line of, "what we're supposed to be doing" on the web but ultimately it requires a lot of complicated code. Far more complicated that one would think at first glance.

[+] qute|10 years ago|reply
quick experiment: after copying the original text 200 times into the text box it starts to be unbearable to write any new text. However, if one just inserts 200k characters with no formatting, the editor doesn't seem to slow down.
[+] ayushgta|10 years ago|reply
This looks interesting especially the part about "Trix sidesteps these inconsistencies by treating contenteditable as an I/O device". We recently started using froala (https://www.froala.com/wysiwyg-editor/v2.0) and are really happy with it so far.
[+] tmikaeld|10 years ago|reply
Also a Froala user, been using CKEDITOR before but switched since Froala worked better and had a simpler API.
[+] m0dest|10 years ago|reply
Interesting naming. The WYSIWYG rich text editor in Google Docs is named Kix. The engine behind Google Sheets is named Trix.
[+] braindead_in|10 years ago|reply
Is there an open source alternative to Kix? I've been looking for WYSIWYG which has the look and feel of a document processor.
[+] morokhovets|10 years ago|reply
Has anyone tried to embed Trix into React? How all this custom tags and polyfills will behave inside react component tree (even though shouldComponentUpdate will always return false)?

There is https://github.com/souporserious/react-trix but it looks like it does nothing at the moment.

[+] picardo|10 years ago|reply
This is a Javascript project, but there is no NPM distribution for it.

Edit: yes, it's not a Ruby gem. I stand corrected.

[+] stephenr|10 years ago|reply
It's also open source. The developers (Basecamp) are obviously deeply invested in the Ruby stack.

If you want to install it with NPM, you could a create pull request with a package.json file and some helpful information for the authors about how to submit to the NPM registry, no?

This is the point of open source software you realise - that you can not just use the software, but that you can help improve it for yourself and others.

[+] sstephenson|10 years ago|reply
No, it's not distributed as a Ruby gem.
[+] lemevi|10 years ago|reply
> This is a Javascript project

It's not JavaScript, Trix is written in CoffeScript.

[+] pbreit|10 years ago|reply
Please tell me this is a humane alternative to TinyMCE, CKEditor, etc?
[+] mmahemoff|10 years ago|reply
Going from the README, the main difference is the architecture.

It creates a layer of indirection between user actions and the DOM. This has two advantages:

* For developers of Trix itself, it eases the pain of cross-browser development - as the README says, contenteditable is inconsistent across browsers.

* For developers using Trix, you get a clean API (Trix.editor) so you can edit the document programmatically without your own cross-browser development.

[+] timdavila|10 years ago|reply
A couple things I noted while playing with the demo at http://trix-editor.org/

* Pressing the <tab> key doesn't insert a tab as I would expect. I'm using Firefox latest on Win8

* The * character doesn't turn into a bulleted list item as I would expect. This is probably more of a nice to have for people use to that behavior in MS Word.

[+] fokinsean|10 years ago|reply
Same tab issue on latest chrome osx
[+] saint-loup|10 years ago|reply
It reminds me of Prosemirror: "By strictly separating its document data structure from the browser's DOM, ProseMirror sidesteps most of the mess that is contentEditable, and ensures that the document stays entirely under the control of the editor." http://prosemirror.net/
[+] rambambam|10 years ago|reply
Last time I saw Basecamp (then 37signals) working on a rich text editor is a long time ago. What happened to WysiHat? I know it had another developer than the two guys who made Trix. What I especially liked about WysiHat was the complete bareness of the toolbar, just plain HTMl links. Is that also possible with Trix?
[+] sstephenson|10 years ago|reply
I was involved with the Wysihat project too. What we found is that its approach, like most other editors', is fundamentally broken. We created Trix to solve the problem. https://github.com/basecamp/trix#different-by-design

I think you'll find Trix's toolbar easy to style however you'd like, but if not, it ought to be straightforward to implement your own using the API.

[+] akulbe|10 years ago|reply
Why are text editors so popular a project? My apologies if that sounds anything less than a legitimate question. I'm genuinely curious.

It seems very common to me, over the last several years, to see $NEW_SHINY_EDITOR, and I wonder why.

Are the alternatives that bad? Or is it just a matter of another dev wanting to scratch their own itch?

[+] jacobsenscott|10 years ago|reply
Yes, they are all terrible. I don't know if this will be any better. They all highlight how bad the web is as an environment to host applications. A rich text editor - something that is a trivial toy project in any other application development environment - is impossible to build on the web in 2015.
[+] stephenr|10 years ago|reply
This is a "WYSIWYG" style rich text editor to embed in a webpage/CMS - its not a desktop "text editor" that a developer might use to write code with.
[+] manigandham|10 years ago|reply
> Are the alternatives that bad?

Yes, almost all of them have major issues. It's really hard to get something that works with all the main text use cases but can also support images and some basic layout features (like drag/drop, move stuff around, etc).

[+] ck2|10 years ago|reply
200kb for css+js

have fun with that on mobile where like all browsers, javascript is single threaded

the reason why we use contenteditable is that it can be done in 15kb and the browser can do it natively, then you just clean up the resulting code on the backend