PixelfearWeb Development by Jason Varga

Using Prism.js Syntax Highlighter within Markdown

Tips, Markdown, JavaScript, Statamic

I’ve recently started using Statamic on this site. It’s been great, up until I needed to put code samples within a blog post (through no fault of Statamic).

Update

This article is pretty much useless now. Statamic now uses Markdown Extra which lets you use Fenced Code Blocks.

Now all you have to do is surround your code with ~~~. You can even add classes.

~~~.language-javascript
var myFunction = function(){
  alert('hello world');
}
~~~

You can read more about this here.

Markdown is nice

Statamic uses Markdown for its content parser. This is great, because it’s so easy to add code blocks. All you need to do is indent the code with a tab (or 4 spaces). You don’t need to worry about encoding the opening and closing tag brackets into their entities. Then, Markdown will wrap the code in <pre> and <code> tags. Great.

But there’s a problem

Since the <pre> tag is out of your control, you can’t add any classes or attributes to it. Not really a problem until you add a syntax highlighter to your project. In my case, I wanted to use Lea Verou’s Prism — mainly because it’s tiny, only 1.5kb — and also because it’s awesome. The issue here is that Prism looks for the language of the class of the tag… which we can’t add ourselves.
For example: <pre class="language-javascript">.

So here’s the solution

One feature of Prism, is that languages can be inherited from parent elements. So if you’re going to be using mostly JavaScript, you can put the class higher up in your hierarchy. For example, <body class="language-javascript">.
Another reason Markdown is great is because you can use HTML throughout it with no issue.

Knowing these two things, we can just wrap our code in a <div class="language-javascript"></div>. Then your code will inherit the language class. Great.

Something like this:

<div class="language-javascript">
    var message = "these two lines should be a code block";
    console.log(message);
</div>

Although, there’s another problem with this. Markdown won’t be parsed within an HTML block. So the code you enter will be rendered as if it were plain old code in your source.

To get your code block to be interpreted as markdown again, all you need to do is add markdown="1" to your <div>.

<div class="language-javascript" markdown="1">
    var message = "these two lines will now be a code block. ahh";
    console.log(message);
</div>

Which will render this:

var message = "these two lines will now be a code block. ahh";
console.log(message);

Drawbacks

Using this technique means you have an extra non-semantic wrapper around each code block. Not a huge deal, but for those code purists there, this may put you off a little.

I’d love to hear a better way to do this.

Comments

blog comments powered by Disqus