Dec 8: Squire: FastMail's rich text editor
This blog post is part of the FastMail 2014 Advent Calendar.
Technical level: low-medium.
We’re going to take a break from talking about our backend infrastructure in this post and switch over to discussing our webmail.
In the beginning, there was text. And really, it was pretty good. You could *emphasise* things, SHOUT AT PEOPLE, and generally convey the nuance of what you had to say. But then came HTML email. Now you could make big bold statements, or small
interesting asides. Your paragraphs were no longer hard-wrapped, but instead flowed according to the size of your screen. Despite some grumblings from a dedicated band of luddites (including a few of the FastMail team :-)), most people decided that this was, in fact, better.
To support rich text editing in our previous interface, we used CKEditor. While not a bad choice, like most other editors out there it was designed for creating websites, not writing emails. As such, simply inserting an image by default presented a dialog with three tabs and more options than you could believe possible. Meanwhile, support for quoting, crucial in email, was severely limited. It also came with its own UI toolkit and framework, which we would have had to heavily customise to fit in with the rest of the new UI we were building; a pain to maintain.
With our focus on speed and performance, we were also concerned about the code size. The version of CKEditor we use for our previous (classic) UI, which only includes the plugins we need, is a 159 KB download (when gzipped; uncompressed it’s 441 KB). That’s just the code, excluding styles and images. To put this in perspective, in the current interface the combined code weight required to load the whole compose screen, including our awesome base library (more on that in a future post…), the mail/contacts model code and all the UI code to render the entire screen comes to only 149.4 KB (459.7 KB uncompressed).
After considering various options, we therefore decided to strike out on our own and wrote Squire.
Making a rich text editor is notoriously difficult due to the fact that different browsers are extremely inconsistent in this area. The APIs were all introduced by Microsoft back in the IE heyday, and were then copied by the other vendors in various incompatible ways. The result of applying
document.execCommand to simply bold the selected text is likely to be different in every browser you try.
To deal with this, most rich text editors execute a command, then try to clean up the mess the browser created. With Squire, we neatly bypass this by simply not using the browser’s built-in commands. Instead, we manipulate the DOM directly, only using the selection and range APIs. This turns out to be easier and require less code than letting the browser do any of the work!
For example, to bold some text, we use the following simple algorithm (actually, this more generally applies to any inline style, such as setting a font or colour too):
- Iterate through the text nodes in the DOM that are part of the
- For each text node, check if it’s already got a parent
it does, there’s nothing to do. If not, create a new
and wrap the text node in it. If the text node was only partially in
the selection, split it first so only the selected part gets
Squire also completely takes over certain keys that are handled badly by default, such as enter and delete. This lets us get a consistent result, and allows us to add the features we want, such as breaking nested quotes if you hit enter on a blank line. And of course we’ve added our own keyboard shortcuts too for actions like changing quote level or starting a bullet list.