Highlighting Code Blocks with Prism

By Cory LaViska on April 17, 2019

Prism is a lightweight, extensible syntax highlighter used by thousands of websites. This tutorial will show you how to highlight code blocks using Prism in Surreal CMS.

JavaScript in progress

Requirements

Installing Prism

You can insert code blocks on any page, but if you want syntax highlighting you'll need to use a library such as Prism. There are two ways to install Prism. One is to download it and host the files yourself. The other is to use a content delivery network (CDN). In this tutorial, we'll be using the popular CDNJS.

Add Prism's default theme by placing the following inside the <head> section of your page. If you want to use a different theme, replace the href with any other theme or a third-party one.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/themes/prism.min.css">

Add these scripts just before the closing </body> tag.

<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/prism.min.js" data-manual></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-markup.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-css.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-javascript.min.js"></script>

The first script is prism.min.js. It's always required and it must have the data-manual attribute.

The other scripts are highlighters for HTML, CSS, and JavaScript respectively. You can remove the ones you don't need, or add additional languages as needed.

Notice

Prism supports many different languages, but it will only highlight the ones you've explicitly included. Be careful not to include ones you won't be using, as additional language files add more HTTP requests and will increase your page load times.

Congratulations! You've installed everything you need to make Prism work. Now we just need to make it work with Surreal CMS.

Integrating Prism

Prism normally runs automatically, but we don't want that to happen in the editor. We need to prevent Prism from changing the markup before content regions are initialized.

For example, Surreal CMS uses the following W3C recommendation for formatting code blocks.

<pre class="cms-code">
  <code class="language-javascript">
    ...
  </code>
</pre>

When Prism runs, it scans the page for code blocks, parses them, and adds a bunch of <span> tags with class names that effectively "highlight" the code. We really don't want those extra tags getting published in the page's HTML, so that's why we added data-manual to Prism's <script> tag.

Since Prism won't run automatically now, we need to tell it when it should run. We also need to tell it to run again when a code block changes. This can be done by listening for the ready and render events to fire on each content region.

You can either copy and paste the following script directly into your page or include it from a separate file (recommended if you're using code blocks on more than one page).

<script>
  if (window.isCMS) {
    // In the CMS...
    document.addEventListener('DOMContentLoaded', function() {
      var regions = document.querySelectorAll('.cms-editable');
      var i;

      for (i = 0; i < regions.length; i++) {
        // Run prism when each region is initialized
        regions[i].addEventListener('ready', function() {
          Prism.highlightAllUnder(regions[i]);
        });

        // Run prism when a code block is re-rendered
        regions[i].addEventListener('render', function(event) {
          if (event.target.classList.contains('cms-code')) {
            Prism.highlightAllUnder(regions[i]);
          }
        });
      }
    });
  } else {
    // ...not in the CMS
    Prism.highlightAll();
  }
</script>

You might notice the window.isCMS conditional — this is one way we can detect the CMS. We're basically telling Prism to run as usual on the live webpage, but to wait for the ready and render events in the editor.

That's it! Now your code blocks will have beautiful syntax highlighting.


If you're having trouble getting Prism to work, feel free to post on the forum or contact us for help.