Reverse engineering GitHub's markdown toolbar

A few weeks ago GitHub introduced a markdown toolbar to their textarea interface in pretty much the style I've been wanting to add to our Project Management Tool for a while. I had been putting off this task because I didn't want to try and solve what I saw as a complicated problem myself when I knew other people were working on it. I was waiting for the perfect "Markdown Toolbar" library to present itself.

There's been lots of activity in the past few years in this space of creating "smart" WYSIWYG editing interfaces. Basically, web developers who like flexible text-based formats like Markdown have their own take on the aging ideas of CKEditor and TinyMCE (which in turn drew inspiration from word processing software like Microsoft Word). In fact, there's now even markdown-compatible interfaces to these WYSIWYG editors, for example: http://ckeditor.com/addon/markdown. But there's plenty of fresh starts as well. My friends at 201-created put together the well thought-out Mobiledoc-kit.

Since working on the CommonMark python library, I've learned the value and ease of developing against a well-defined test specification when dealing with text i/o. (That's also why I think CommonMark is such an important project in the sea of unspecified Markdown libraries). I learned that there's really no theoretical knowledge required: although I know the terms, I couldn't tell you the difference between parsing "top-down", "bottom-up", "recursive descent", etc.

I've always appreciated the ideals of reverse engineering, "black box" design. And to me, it sort of takes the boring parts out of developing something: project planning and writing specifications. If you have well-defined inputs and outputs, all you're left with is the fun part of writing the code. Now I understand why there are so many SNES emulators out there.

The first step is copy-and-paste the DOM elements: markdown_toolbar.html. Looking at the HTML gave me some intriguing clues into how this works: The buttons use the data-prefix, data-suffix, data-block-prefix, and data-block-suffix variables to define what sort of text is added around the cursor. With this piece of info, I put the heart of this re-implementation in markdown_toolbar_controller.js using the unit tests at markdown_toolbar.spec.js. The controller is connected to the DOM with markdown_toolbar.js.

The code now works for basic use cases. It doesn't behave in the exact same way as GitHub's toolbar yet, and there are minor bugs. But the path ahead is straightforward: I just need to add more unit tests (with use cases taken from GitHub's toolbar), and I need to expand the breadth of my unit testing. For example, there are parts of markdown_toolbar.js that should be tested, like the lastHotkey and lastText functionality that records what happens when you click the same button twice.

After development is complete, it would be nice to package markdown-toolbar into a separate library that can be integrated anywhere.

Update (March 15, 2017):

You can now use this package as a jQuery plugin: https://github.com/nikolas/markdown-toolbar