Why and How We Implemented Trix for Solid

After 1 year of tinkering with the note-taking experience in Solid, we’ve decided to trust Basecamp’s Trix editor to do a large part of it for us. Here’s the why-s and the how-s.

1. Handles management of contenteditable

Contenteditable is the attribute you pass to any HTML tag in order to make it editable. Managing contenteditable is a known cause of headaches among developers. Here’s a bit of context to tell you why it is so:

Today, the contenteditable we have is adapted from the execCommand APIs, developed by Microsoft for Explorer 5.5. Release date of that Explorer version? July 2000.
This execCommand API was reverse-engineered and adapted for other browsers, which (unsurprisingly) led to a ton of inconsistencies. The number of actions to account for is also immense. Think of all the actions you take when writing things down… I, for one, go back on what I wrote, skip a few lines, delete some, bold stuff, emphasize other stuff, etc. So the tree of possible actions to account for is tricky.

On the Hackernews thread for Trix, user nmjenkins explains:

“Stuff like hitting “enter” on the keyboard – all sorts of crazy stuff happens (new tags being added, nothing consistent between browsers, generally doesn’t do what you want). […] You generally can’t trust the browser to get you from state A -> B and have to do it yourself.”

Since Basecamp outsourced this part of their work as Trix, we’re happy to use it.

2. Reduces our codebase

This one is rather obvious and is a direct result to the point above. Trusting Trix to handle contenteditable means we’re not coding that part. It saves time and reduces the codebase. Less stuff to handle and update => happy developers.

3. Preps for many most-wanted updates on Solid

Trix features quite a bit more stuff than just this handling of contenteditable. And many of these things are most-wanted iterations on Solid’s featureset. Here’s the top 3 features Trix helps us prepare for:

  • All the formatting. Many users have asked for formatting features such as T1, T2, bold, italics, underline. Trix has it
  • More formatting still: lists. Ordered and unordered lists also become a lot simpler thanks to Trix. They’re in the scope of the formatting discussions we’re having within the Solid team at the moment.
  • Docs and uploads. We’re gearing up to add docs into Solid. Trix has a built-in management of doc uploads and supports drag-and-drop-to-upload. Two big wins that we won’t have to deal with on our own.
  • Undo / Redo. Cmd+Z has become a standard when editing anything on desktop. We get it: you want to be able to mess up and around on Solid, erase it all and keep going. Hopefully we’ll have this in place soon.

4. Open source means we’re not going in alone.

Trix is open source which means everyone interested can contribute to the project. Developers can help by coding, that’s the most obvious part. But most everyone can suggest improvements and file bugs.

What’s in it for us and you? Trix will evolve quicker than our 6 developers would allow on their own.

Here’s an example with the discussion on autolinking URLs. Right now, typing https://google.com via Trix will show up as plain text. Some wish Trix to interpret it as a link instead. It turns out it’s not that easy, so 5 people have suggested possible solutions already. That’s neat

Brace yourselves, here come the caveats!

Adding Trix into our codebase isn’t exactly like replacing an old lego block with a new one. There was a bit more to it.

Since we’re implementing Trix on an existing codebase that started over a year ago (for Solid) - or even 6 years ago (for Wisembly’s backend which has shared parts with Solid), we encountered roadblocks.
Namely, we used to save everything in plain text in our backend. But Trix saves in HTML to bypass the whole execCommand and browser-based formatting choices. So when you type a note and hit enter, it interprets what you just wrote, and saves it as an HTML line.

So we had to adapt to saving in HTML, keeping two important things in mind:

1. Security (prevent malicious content like scripts to land on our Database)
2. Exports (exporing notes used to be based on plain text, we had to adapt to sending HTML).
3. Native apps support (iOS being in the works fast-tracked this)

Thankfully, we still had a few… tricks up our sleeves 😉

1. Security through sanitization: malicious content shall not pass

When we receive a note, first we’ll strip it down from all tags except the ones we specifically allow.
Then, we’ll check that the cleaned up note is identical to the one we initially received. If it is identical, we accept it and print it to the database. If it’s not, we’ll reject it.

Doing so ensures we’re not allowing any scripts into our DB.

2. On exports: bye bye plain text, hello markdown

So, since we used to store all notes in plain text, that was also our go-to format for exports. You can’t really assume that all services you’ll export to, and all your webhooks will work in HTML. So now that we save notes as HTML, we’re converting said hooks to markdown.

So here’s what happens when you export:

1. We take your request to export
2. We convert all the notes from HTML to markdown
3. If this conversion fails, we fallback by deleting all HTML from the code and export this forced plain text version.
4. Aaand your export is ready.

3. Native apps support

HTML is the standard for web content. It’s web browsers job to interpret it. But when it comes to native apps (think iOS or Android), that’s another story. iOS only accepts basic formatting tags as an input.

So while building sanitization for step 1), we also made sure to only validate tags that iOS could understand.

That’s about all we had to account for. We’re hopeful that this update will help us improve the note-taking experience for all users, as well as help us focus on all the other important things we have on our plate.

This new implementation of Trix is now live on Solid, sign in to try it out!

Have you considered delegating contenteditable like we did? If so, what project did you choose? We’d love to know!