The markItUp text editor

Submitted by mimec on 2013-04-03

As I already explained, version 1.1 of WebIssues will allow using a special markup language when editing comments and descriptions. The syntax will be a hybrid of BBCode, Wiki and various other markup languages. Obviously it's hard to expect that the users will remember Yet Another Markup Language. Instead, they will use a familiar toolbar and key shortcuts to make selected text bold or italic, create a hyperlink or insert a block of code. I decided to use markItUp because it's simple, lightweight (the original uncompressed script is just 20 KB long) and fully customizable. Unlike some other editors, it's not designed for any particular markup language (like markdown or wiki syntax), but lets you design a custom toolbar with whatever markup you need.

After playing with markItUp for a while, I decided to customize it a bit more by modifying the script. It could already generate a preview using AJAX and has multiple ways of showing it - in a popup window, embedded iframe or a custom HTML element. I decided to use the custom element, but I wanted it to be shown dynamically when the preview is first invoked, just like in the two other modes. I also integrated it with prettify, about which I wrote last time, so that syntax highlighting works in the preview.

I also slightly changed the way the markup is added. First, in my version, the openWith/closeWith text is not added to empty lines (or lines with nothing but whitespace). Second, the closeBlockWith text is added before any trailing newlines and other whitespace. It works better this way, especially if you want to apply bold or italic to multiple lines (each line is treated as a separate block, so it must be wrapped in separate bold/italic tags). Finally I removed the special handling for Ctrl and Shift keys when clicking on the toolbar. It's hard to remember and can be confusing, so I decided to simply remove it.

Just like with Prettify, I minified the whole thing using the Closure Compiler, this time in simple mode, because advanced doesn't work too well with jQuery plug-ins. I also had to replace an eval() with direct call to the preview() function, because eval() wouldn't work with minified code. The final script is just 10 KB long. The unminified version of both this script and my version of Prettify are available in the trunk/tools subdirectory of the WebIssues SVN repository, in case you're interested.

Note that obviously I had to implement a similar editor in the Desktop Client, which uses a native QPlainTextEdit to edit the comments and descriptions. JavaScript was not an option here, but adding a few toolbuttons and reimplementing the relevant function in C++ was very straightforward. By the way, I recently also rewrote the entire markup processor, which converts the markup to HTML and also exists in two versions, PHP and C++. It was the third or forth time I wrote it from scratch, but this time I decided to do it "the right way". Instead of a very long, convoluted loop with a state machine, I decided to use a recursive descent parser, which is very simple, because the markup language has a LL(1) grammar with just a few production rules. The code is now slightly longer, but incomparably easier to understand, plus I fixed a few remaining bugs.

Some of you might wonder why I didn't decide to implement a WYSIWYG editor in WebIssues. They are large, complex beasts, which may be useful for large CMS systems designed to be used by non-technical people who like to edit their articles as if they were using MS Word. For a relatively small project like WebIssues, it would be an overkill to include a word processing package in it. Besides, these editors don't always produce valid HTML, and they don't work consistently across various browsers (not to mention the Desktop Client). What's worse, despite the tempting naive implementation (which uses htmlspecialchars_decode to circumvent WebIssues' built-in XSS protection!), it's actually very difficult to sanitize and validate the resulting HTML. Instead, WebIssues will still support the old style plain text format, with no special processing (except for turning URLs into links), which indeed is truly WYSIWYG. Depending on the level of technical skills of the majority your users, you will be able to choose the either plain text or text with markup as the default format.