Simple JS Examples
While I was writing this post about JavaScript I wanted to make an easy way to include JavaScript in my markdown and also show output from the scripts. I came up with the following idea. What if I can mark each example with a CSS class, I called it runnable
, and then evaluate the examples on a page and put the output their results into a pre
element below the code. There are a couple design decisions that went into the implementation.
First, I am putting raw HTML in the markdown to assign the CSS class. This also allows me to use the Google Code Prettify JS and CSS to add line numbers and syntax coloring to each example. I am not assigning runnable to all code elements so I don't want to use my base style sheet or process all pre
elements.
Second, when the runnable class is found, the content of that DOM element will be considered code and will be run. Moreover, a function called log
is defined in a way that will allow it to be output to a pre
element below the code. For example, the following code in one of my markdown files:
<pre class="runnable prettyprint lang-javascript linenums"> var x = 1; var y = 2; var z = x + y; log(z); </pre>
will generate the following output:
The code for processing the runnable
segments is defined in a script at the bottom of the page (actually a template page):
<script>
$(document).ready(function() {
$('.runnable').each(function(index,element){
var code = $(element).text();
$('<pre id="log'+index+'"></pre>').insertAfter(element);
code = "function log(str){$('#log"+index+"').append(str+'\\n');}\n"+code;
try
{
eval(code);
}
catch(err)
{
$('#log'+index).append(err.message+'\n');
}
});
prettyPrint();
});
</script>
This script uses the standard JQuery document ready pattern. Once the page is loaded, I look for elements with the CSS class runnable
. For each element I:
- Grab the content
- Append a
pre
element after the code element. This new element is used for output and has an id based on the index of the runnable,log+<index>
- Define a function called
log
that will append text to thepre
element. This function definition is prepended to the code - Evaluate the code
- Re-run Googles
prettyPrint
to make sure all the code examples are formatted
Originally I didn't have a try-catch
around the eval
statement. This is a mistake in general, but I also discovered that by including the catch
, I could display error messages as well. For example, the following example is defined as a runnable and throws an exception which will be printed in the log.
var x = []; log(x[1]);
As I write more JavaScript examples, I think this new code, which is defined in a template, will make the markdown for posts even easier to write.