Easy Code Highlighting in Ghost with Prism

PrismJS provides an easy, extensible way to take care of code and syntax highlighting on websites. Find out how to dynamically load Prism with support for any code language on your Ghost blog!

Easy Code Highlighting in Ghost with Prism

Background

I had a tough time searching around for the ideal solution on this. PrismJS provides an easy, extensible way to take care of code and syntax highlighting on websites. It's a really popular library that a ton of bloggers use for tutorials.

There are a couple of ways of skinning this cat, and some folks have already provided great tutorials here and here. However, I wanted something a bit more dynamic. I didn't want to load an additional 20-30Kb + of data on every page when I'm not posting code snippets on those pages. Also, I wanted the ability to dynamically load the languages I want to only if necessary.

So I mixed some solutions of my own together with some simple javascript.

Overview

  1. Download PrismJS and add the language components to your assets folder
  2. Edit your post.hbs file to dynamically load the prism libraries
  3. Re-upload and activate your theme
  4. Profit and use PrismJS style <pre> and <code> tag styling in your blog!

Guide

Step 1

Go to the PrismJS Download Page. For this since we can dynamically load whatever languages you need, you should only select the core modules and also the default languages if they make sense for you. The only necessity here is to make sure you include the autoloader module.

Plugin Selection Page

For this you will also need to download the language components file here (the link says download all grammars). Notice how we are at 16.04 KB!!!

For this you will also need to download your current theme. Go to your blog admin site or app and download / extract it.

Download themes in ghost admin

Once you have your theme handy and have downloaded prism.js, prism.css, and components (grammars) we want to move the prism files into your themes folder. Make a new directory called prism inside your assets theme folder. Copy the prism.js and prism.css into your newly created prism folder. Lastly extract the components and copy them into a components folder (full path should be /assets/prism/components/*).

Great Step 1 is now complete!

Step 2

For this step we want to open our post.hbs file within the root theme folder. You can use your favorite editor (I like VSCode or Atom). You want to copy and paste the following code into the end of this file before the {{/contentFor}} line.

<script>
            
// Detect if we have code tags on the page.
var codeElement =  document.querySelector("pre > code");
if (typeof(codeElement) != 'undefined' && codeElement != null)
{
  // Create CSS Element
  var prismCSS = document.createElement('link');
  prismCSS.rel = "stylesheet";
  prismCSS.type = "text/css";
  prismCSS.href = "/assets/prism/prism.css?v=1"

  // Create PrismJS Element
  var prismScript = document.createElement('script');
  prismScript.type='text/javascript';
  prismScript.src="/assets/prism/prism.js?v=1";

  // Set Components Folder because of asynch script loading
  prismScript.onload = function() {
    Prism.plugins.autoloader.languages_path = '/assets/prism/components/';
  };

  // Load script and css in the DOM
  document.head.appendChild(prismCSS);
  document.head.appendChild(prismScript);
}
</script>

What we are essentially doing is:

  1. Checking if our post has PrismJS supported elements (code tags inside of pre tags).
  2. If the tags exist we are dynamically creating a css file link as well as a script tag and loading them into the HTML head section.

Save this file.

Step 3

Compress, re-upload, and activate this new theme.

Step 4

In your blog you can now do something like this to take advantage of the new functionality. You can also use the standard markdown syntax with the triple backtick (eg: ```python```).

Ghost Koenig Editor HTML Element

This is equivalent to:
markdown-prism-syntax-v2

And that will yield this on your page:

import requests

class Ghost:
    def __init__(self):
        pass

Final Thoughts

Once you know how to do it, getting this to work is pretty easy and painless. Let me know what you think down in the comments! If you have a better way of doing things I'm also open to ideas. A couple of key features I was looking for:

  1. Dynamically load whatever language I want
  2. Reduce (de-bloat) unnecessary script loading on my Ghost posts page
  3. Great syntax highlighting on my blog!

You could actually take this a step further if you were hosting your own blog and statically serve the prism assets through Nginx so you didn't have to worry about managing it inside your theme folder. I might do a tutorial on that next. This, however, should also work for folks that are using the Ghost cloud SaaS service as well.