How to set up and configure Prism.js with Ghost CMS

Prism.js and Ghost CMS are integrating seamlessly. Adding Prism.js to your Ghost blog is a low-effort task and will give your blog an extra touch of professionalism. In this tutorial, I will be teaching you how to add Prism.js to Ghost and show you a few examples of how to torder to highlight younicelyice way with Ghost.

What is Prism.js?

Prism.js is a free and open-source syntax highlighter used on websites. It is capable of supporting almost any programming language, as well as providing some themes for nice styling and plugins to extend its functionality. By adding Prism.js to your Ghost blog you can continue to add code blocks in your posts, but they will get nicely and beautifully way. If you are ready, let's get to it!

GitHub - PrismJS/prism: Lightweight, robust, elegant syntax highlighting.
Lightweight, robust, elegant syntax highlighting. Contribute to PrismJS/prism development by creating an account on GitHub.

Up and running with Prism.js

At this blog, I serve Prism.js from my own server network as I have customized the package of languages, themes, and plugins in combination with the design I have made for the website.

For this tutorial, I will show you how to serve Prism.js from an external CDN. You are of course welcome to download Prism.js and install it on your server. However, if you just want to get going and have an easy way of updating Prism.js in the future, you should use this dynamic way.

If you like me take privacy seriously - I would highly recommend making sure that the checksum of the scripts ttorder to make sure nothing has been tampered with by a hacker. 🤯

Where to find Prism.js?

The sweet people at CDNJS are hosting Prism.js and you can use it for free - just as I will show you in this article.

cdnjs - The #1 free and open source CDN built to make life easier for developers
Simple. Fast. Reliable. Content delivery at its finest. cdnjs is a free and open-source CDN service trusted by over 12.5% of all websites, serving over 200 billion requests each month, powered by Cloudflare. We make it faster and easier to load library files on your websites.

CDNJS is another awesome project hosted by Cloudflare, I use them for many projects and trust their scripts. You can find the whole library for Prism.js at CDNJS here:

prism - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers
Lightweight, robust, elegant syntax highlighting. A spin-off project from Dabblet. - Simple. Fast. Reliable. Content delivery at its finest. cdnjs is a free and open-source CDN service trusted by over 12.5% of all websites, serving over 200 billion requests each month, powered by Cloudflare. We make…

Implement Prism.JS in Ghost CMS

The first thing we have to do is locate the Code Injection area in our Ghost backend. If you are logged in as an administrator in Ghost, it is easy to find under the gear wheel.

code injection cms, prism.js ghost
Settings > Code Injection in Ghost CMS

Configure Site Header

The header is home to styling and we will of course be adding the core Prism.js CSS files here. If you would like to learn more about themes and plugins you can include them here, check out their website.

I am using the theme Tomorrow Night in combination with several of their plugins here on this blog. Some of them allow you to see line numbers, and highlighted code and copy the entire code block easily.

Your Site Header could look like this:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" integrity="sha512-vswe+cgvic/XBoF1OcM/TeJ2FW0OofqAVdCZiEYkd6dwGXthvkSFWOoGGJgS2CW70VK5dQM5Oh+7ne47s74VTg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-highlight/prism-line-highlight.min.css" integrity="sha512-nXlJLUeqPMp1Q3+Bd8Qds8tXeRVQscMscwysJm821C++9w6WtsFbJjPenZ8cQVMXyqSAismveQJc0C1splFDCA==" crossorigin="anonymous" referrerpolicy="no-referrer" />

I simply copied the code snippets from CDNJS by selecting Styling in the Asset Type.

Copy Link Tag from CDNJS
Copy Link Tag from CDNJS

What is included in the link tag?

  • Rel defines the relationship between a linked resource and the current document.
  • Href is the hyperlink telling the browser where to download the asset from.
  • Integrity is running a SHA-256 hash sum against the downloaded file from CDNJS. This is to make sure that the file has not been modified during download by a "man in the middle".
  • Crossorigin makes sure that CORS headers are set to allow you and your clients to access the specific file from CDNJS.
  • Referrerpolicy controls how much referrer information (sent with the Referer header) should be included with requests.

Our footer will contain javascript (JS) responsible for doing the heavy lifting when it comes to functionality. To make Prism.js work, you need the core Prism.js script.

<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js" integrity="sha512-7Z9J3l1+EYfeaPKcGXu3MS/7T+w19WtKQY/n+xzmw4hZhJ9tyYmcUS+4QqAlzhicE5LAfMQSF3iFTK9bQdTxXg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

You can add support for other programming languages in two ways. You can do it by adding each programming language as a link in the header or you can use the autoloader. The autoloader script will detect which languages you are using on a specific page and then load the language(s) dynamically.

Below is an example of how you can add line number functionality and autoloader functionality.

<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js" integrity="sha512-7Z9J3l1+EYfeaPKcGXu3MS/7T+w19WtKQY/n+xzmw4hZhJ9tyYmcUS+4QqAlzhicE5LAfMQSF3iFTK9bQdTxXg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.js" integrity="sha512-BttltKXFyWnGZQcRWj6osIg7lbizJchuAMotOkdLxHxwt/Hyo+cl47bZU0QADg+Qt5DJwni3SbYGXeGMB5cBcw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js" integrity="sha512-SkmBfuA2hqjzEVpmnMt/LINrjop3GKWqsuLSSB3e7iBmYK7JuWw4ldmmxwD9mdm2IRTTi0OxSAfEGvgEi0i2Kw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>document.body.className += ' ' + 'line-numbers';</script>

The above first three lines make total sense, but what the heck are you doing on line 4 Christian? 🤔

The short explanation is that the line numbers plugin from Prism.js only adds line numbers to HTML elements, which got the line-numbers attribute attached. That is (in my opinion) super annoying as I am documenting code in a lot of other languages. 😫

To exploit that I am adding the line-numbers class (attribute) to the entire document body. This makes all the code blocks being rendered with line-numbers. If you read the official documentation you will also see that it is the recommended approach. If you add the line and inspect your website, you will see that line numbers are now being added.

prism.js line numbers
Line numbers added for the body

How to use Prism.js with Ghost CMS?

Alright, now Prism.js is added to our Ghost CMS - let's start using it. This is (fortunately) the easiest part. 😝 You got three options:

  1. Using the Koenig editor (Default Ghost editor)
  2. HTML
  3. Markdown

I have added examples to show you how to use Prism.js with all three options, below. The goal is to achieve this with C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TwcTutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            string message = "Hello from Tech with Christian (TWC)";

            Console.WriteLine(message);
        }
    }
}

Koenig Editor

To enable a code block for C# in the Koenig editor, we have to write the following: "```csharp". Inside this code block, we can now paste our code from above and let Ghost render it nicely using Prism.js. Here is what it looks like in the backend:

Ghost Code Block, Koenig Code Block, prism.js
Koenig Code Block

When rendered, it becomes the nicely formatted code above.

HTML

I always use HTML, when I have to highlight some specific lines of code. This would require you to include another plugin named Prism Line Highlight. An example of how the HTML code would look like to show the C# code is here:

<pre class="line-numbers language-csharp"><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TwcTutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            string message = "Hello from Tech with Christian (TWC)";

            Console.WriteLine(message);
        }
    }
}
</pre></code>

You have to put that into an HTML block, but that's it.

Markdown

If you prefer to write your posts in markdown, you can add a code block pretty much the same way as when you add a new code block with the Koenig Editor.

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TwcTutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            string message = "Hello from Tech with Christian (TWC)";

            Console.WriteLine(message);
        }
    }
}
```

The markdown block would remove line number 1 and 20 and only show the code you added.

The result if you have added Prism.js to your header and footer scripts correctly, is pretty neat, right?

Code Highlighting examples using Prism.js with Ghost

Before we sum up this article about adding Prism.js to Ghost CMS I will show you a few examples of some code highlighted with Prism.js.

JSON

{
    "glossary": {
        "title": "example glossary",
		"GlossDiv": {
            "title": "S",
			"GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
					"SortAs": "SGML",
					"GlossTerm": "Standard Generalized Markup Language",
					"Acronym": "SGML",
					"Abbrev": "ISO 8879:1986",
					"GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
						"GlossSeeAlso": ["GML", "XML"]
                    },
					"GlossSee": "markup"
                }
            }
        }
    }
}

C#

public static TResult Aggregate<TSource, TAccumulate, TResult>(
    this IEnumerable<TSource> source,
    TAccumulate seed,
    Func<TAccumulate, TSource, TAccumulate> func,
    Func<TAccumulate, TResult> resultSelector)
{
    if (source == null) throw Error.ArgumentNull("source");
    if (func == null) throw Error.ArgumentNull("func");
    if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
    
    TAccumulate result = seed;
    foreach (TSource element in source) {
        result = func(result, element);
    }
    return resultSelector(result);
}

YAML

 doe: "a deer, a female deer"
 ray: "a drop of golden sun"
 pi: 3.14159
 xmas: true
 french-hens: 3
 calling-birds:
   - huey
   - dewey
   - louie
   - fred
 xmas-fifth-day:
   calling-birds: four
   french-hens: 3
   golden-rings: 5
   partridges:
     count: 1
     location: "a pear tree"
   turtle-doves: two

Docker

# syntax=docker/dockerfile:1
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app
    
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
    
# Copy everything else and build
COPY ../engine/examples ./
RUN dotnet publish -c Release -o out
    
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "aspnetapp.dll"]

Powershell

Get-CimInstance -Class Win32_SystemDriver |
  Where-Object {($_.State -eq 'Running') -and ($_.StartMode -eq 'Manual')} |
    Format-Table -Property Name,DisplayName

Python

# Program to sort alphabetically the words form a string provided by the user

my_str = "Hello this Is an Example With cased letters"

# To take input from the user
#my_str = input("Enter a string: ")

# breakdown the string into a list of words
words = [word.lower() for word in my_str.split()]

# sort the list
words.sort()

# display the sorted words

print("The sorted words are:")
for word in words:
   print(word)

Commands

Write-Host `
'Hello' `
'from' `
'Tech with Christian!'
Hello from Tech with Christian!
Write-Host 'Goodbye from Tech with Christian!'
Goodbye from Tech with Christian!

Summary

Prism.js is a very nice tool when you want to take your Ghost blog to the next level in terms of user experience and format your code in a nice and easily readable way. It required a low effort from you to add the functionality.

It will for sure hold on to your visitors for longer time and maybe lower the bounce rate because they like to read your content and it doesn't hurt in their eyes.

If you got any questions, please let me know in the comments. Until next time - happy blogging! ✌️

You've successfully subscribed to Tech with Christian
Great! Next, complete checkout to get full access to all premium content.
Error! Could not sign up. invalid link.
Welcome back! You've successfully signed in.
Error! Could not sign in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.