Edit (July 2017): We now use React with TypeScript.

So at Esper we made this tool to make our lives easier.

Oblivion is a preprocessor for JavaScript source files. It allows the programmer to embed raw HTML code into JavaScript with very few modifications. Only local variable names need to be inserted, allowing these HTML elements to be modified programmatically – and safely.

Have you ever wanted to copy-paste HTML code directly into a JavaScript string?

var s = '
  <span class="example">Welcome!</span>

Oops, that’s invalid. JavaScript doesn’t support line breaks in string literals. Instead you would have to write something like:

var s =
+'  <span class="example">Welcome!</span>'

This required more edits than we wanted, but why not. Now something we often do is modify child nodes based one some conditions. We use jQuery to produce a dom node from a string, maybe as follows:

var view = $(
+'  <span class="example" id="msg"></span>'

var text = isNewUser(user) ? "Welcome!" : "Hello!";

Huh. This assumes that no other element in the whole document may be identified by id="msg". If not, the selection $("#msg") may hold the wrong element. What we want here is trade our global identifier for a local JavaScript variable. This is done as follows:

var view = $('<div/>');
var msg = $('<span class="example"/>');
var text = isNewUser(user) ? "Welcome!" : "Hello!";

or maybe we will push jQuery to its limits and write the following:

var view = $('<div/>');
$('<span class="example"/>')
  .text(isNewUser(user) ? "Welcome!" : "Hello!");

Nice. No more global identifier. Does it look like HTML? No. Do you need to create something like a modal, with a complex structure and several placeholders for text or HTML elements? Still without using global id‘s? And everything embedded in your JavaScript source where you need it?

This is where we figured something should be done. We came up with oblivion, a preprocessor for JavaScript files that lets us write HTML naturally and bind local variables to the nodes we want without dismantling the HTML structure.

Our example written using oblivion syntax is:

/* oblivion snippet */
<div #view>
  <span class="example" #msg></span>
/* regular JavaScript */
msg.text(isNewUser(user) ? "Welcome!" : "Hello!");

Additionally, Oblivion automatically packs our variables (view, msg) into a _view object that can be easily passed to other functions. This means that in the example above, view and msg are also available as _view.view and _view.msg.

Oblivion parses the HTML template statically so if your HTML code contains a syntax error, oblivion will indicate its exact position in the source file.

And really, all oblivion does is produce this:

/* Auto-generated from <stdin> by oblivion. Better not edit. */ /* oblivion snippet */
var _view = {};
var _1 = $("<div/>");
var view = _1; _view.view = _1;
_1.append(document.createTextNode("\n  "));
var _2 = $("<span/>").attr("class", "example").appendTo(_1);var msg = _2; _view.msg = _2;_1.append(document.createTextNode("\n"));
/* regular JavaScript */
msg.text(isNewUser(user) ? "Welcome!" : "Hello!");

Note how the line count is the same in both the input and the output. If a runtime error is reported on line 8, we know that the error is on line 8 in the source code as well.

Oblivion is free software distributed under the terms of a BSD license. Enjoy!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s