Understanding Terrible Code, Part One:
Writing a CKEditor Plugin
Exposition: Why should you care about a random text editor?
Modding CKEditor is a well-designed exercise in self-flagellation.
CKEditor is a text editor plugin that works with rich text (bold, italics, tables, links, etc.). If you’ve ever used Gmail or Hotmail, you’ve used something similar. CKEditor is relatively easy to use, powerful and has lots of features, and it’s used everywhere. But while the code is well written and well documented, at a macro level there are terrible design things going on, and if you want to modify it, you’ll be glad you never did end up getting that gun license after all…
Since I’ve been wrestling with it for quite a while now, I wanted to share my thoughts:
- In case you happen to be forced to alter CKEditor as well. Hopefully this will be a useful breadcrumb trail.
- To convince myself I’m not faking it. CKEditor has well written source, in the sense of comments and indents and other things they do well, so someone could argue “maybe they’re doing it well and you just don’t get it.”
This is a perfectly valid counterargument. The best way to figure out if I’m faking it is to actually try and explain why it’s bad, and see if this post turns into “CKEditor is an architectural marvel” in the process.
- Complaining is whining unless you can explain why, and how to make things better.
- I need to understand this stuff myself, and nothing helps with understanding like trying to explain.
- Because I’ve been staring at this for days and need to say something.
Act One: Parallel Universe APIs
CKEditor dialogs are used for special properties. If you want to add a link, you would create a dialog to set the URL.
And then you see this:
(This is actual dialog code that CKEditor uses to show a link dialog.)
Is that HTML? Yup – it looks like a <select> – there’s a list of options (items), and an id, and even a label.
six ten tabs in, and it wouldn’t take you an hour of sorting to figure out what a dialog that’s basically a handful of selects and some text fields is doing.
By the way, there’s CSS too:
1 2 3 var basicCss = 'background:url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ') no-repeat ' + side + ' center;' + 'border:1px dotted #00f;';var basicCss = 'background:url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ') no-repeat ' + side + ' center;' + 'border:1px dotted #00f;';
Let’s establish some of the downsides of this mixed-content architecture:
- Wading a thousand four-hundred line morass of mixed behavior and content every time you want to change things
- No way to test the layout of your dialog without loading all of CKEditor (as opposed to HTML, which can be tested by anyone with a web browser)
- Oh and if you miss a brace, it’s not like missing an angle bracket – everything dies. JS is brittle. Did I mention you have to reload all of CKEditor to test your fixes?
Another option: Don’t use a 1-1 HTML counterpart, but use a simplified meta-language.
This rant is just barely getting started. Every time I work on CKEditor I’ll make sure to add more.