Library of The Week: CodeMirror

Have you ever edited one of your source files directly on the GitHub website? Or have you prettified JSON or JavaScript code with the Online JavaScript Beautifier? Both of these sites require a component with editable text content. This week we'll take a closer look at how this feature works under the hood.

When you talk about an "embedded web editor", developers usually imagine a WYSIWYG editor for HTML like CKEditor. But source code editing is a different use case with its own specialized editors. No WYSIWYG, no images and just a single monospaced font. Instead, these editors have autocomplete, bracket matching and syntax highlighting.

Since there is more than one source-code editing component available, the fundamental question is which one to use for your app. The two examples mentioned above use two of the most popular; GitHub is powered by Ace while JS Beautifier prefers CodeMirror. Judging from the comparison on Wikipedia, they look pretty similar. So the choice is mostly about your personal preferences and your project's specific requirements. In the remainder of this article, I am going to focus on CodeMirror.

Although there are projects implementing a full featured cloud IDE, as a developer you are more likely to use an editor component in a less ambitious situation. A typical one is a CMS for power users that favors Markdown syntax over WYSIWYG. (Just as an aside, this blog is deployed on Ghost, which uses CodeMirror as well.) But it isn't only about editing and rendering Markdown. If you have a DSL, you can implement your own custom syntax highlighter. Or do you need to modify configuration files in a web administration interface? CodeMirror even has Nginx support.

Another common requirement is authoring markup with placeholders using a templating library. Together with the appropriate CodeMirror mode (e.g. Jinja2 or Mustache), you get a powerful syntax-aware editing solution.

If you open the Mustache demo page, you'll see how simple it can be to add support for a new syntax.

CodeMirror.defineMode("mustache", function(config, parserConfig) {
  var mustacheOverlay = {
    token: function(stream, state) {
      var ch;
      if (stream.match("{{")) {
        while ((ch = stream.next()) != null)
          if (ch == "}" && stream.next() == "}") {
            stream.eat("}");
            return "mustache";
          }
      }
      while (stream.next() != null && !stream.match("{{", false)) {}
      return null;
    }
  };
  var mode = CodeMirror.getMode(config, parserConfig.backdrop || "text/html")
  return CodeMirror.overlayMode(mode, mustacheOverlay);
});

Configure the editor to use the new mode as follows:

var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: "mustache"});

CodeMirror is a complex component with many customization options and third-party add-ons. You can also interact with the editor through its JavaScript API. For more complete information, refer to the CodeMirror manual.

Roman Krejčík

Roman Krejčík