Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

prismjs
javascript
html
communitycreator

How to make PrismJS editable

Haseeb Majid

In this article, we will go over how you can make PrismJS code blocks editable and force PrismJS to re-render so the code blocks will be syntax highlighted again.

Introduction

PrismJS can be used to add syntax that highlights code blocks on our website. For a personal project of mine, I needed to allow the user to paste in their own (docker-compose) yaml files. So, let’s take a look how we can let a user first edit a code block and then re-run PrismJS to add syntax highlighting.

index.html

So, our HTMl will look something like this.

Note: When I refer to “code block” I am referring to entire thing including the pre and the code tags.

HTML

<head>
  <link
    rel="stylesheet"
    type="text/css"
    href="stylesheets/prism.css"
    rel="stylesheet"
  />
</head>
...

<pre
  onPaste="setTimeout(function() {onPaste();}, 0)"
  id="editable"
  contenteditable
>
  <code id="yaml" class="language-yaml"></code>
</pre>
<script src="javascript/prism.js"></script>

In this file, we import the prism.css stylesheet, there are many themes you can choose from in this example, but we will use the default theme. We will also import prism.js. These are the two files required to use PrismJS.

HTML

<pre
  onPaste="setTimeout(function() {onPaste();}, 0)"
  id="editable"
  contenteditable
>
  <code id="yaml" class="language-yaml"></code>
</pre>

Next, we create the code block on web page.

Note: the class on the code tag is language-yaml.

To use PrismJS, we need to give the code a tag of a class of language-x, where x is the language we want syntax highlighting for. You can find a full list of supported languages here.

To allow users to paste and edit the code block, we add contenteditable to the pre tag. The reason we add it to the pre tag and not the code tag is, when PrismJS runs the code, it will edit the code block to include span's and other html elements to do the syntax highlighting – this makes it a lot harder for the user to copy and paste when you edit the code tag as apposed to the pre tag. The pre tag also has onPaste="setTimeout(function() {onPaste();}, 0)", which means that after the user has pasted into the pre tag, this function will be called. In this case we call a function called onPaste(). However, we use a setTimeout so that the browser has enough time to update the pre tag; else, the pre/code tags will contain the previous text before the paste.

JavaScript

Now, the user can paste directly into the code block, but how do we force a re-render? Let’s take a look at the onPaste function that is called every time the user pastes into our code block.

JS

function onPaste() {
  const editable = document.getElementById("editable");
  const dockerCompose = editable.innerText;
  editable.innerHTML = '<code id="yaml" class="language-yaml"></code>';
  const yaml = document.getElementById("yaml");
  yaml.innerHTML = Prism.highlight(dockerCompose, Prism.languages.yaml, "yaml");
}

So, first, we get the editable element (our pre tag). Next, we get the innerText of said element. This should be the new content the user wants to paste into the pre tag. Sometimes, when you copy/paste into the code block, the old code tag gets deleted so, just in case, we add the code tag back in as this is where PrismJS will render our new YAML code. This is done with, editable.innerHTML = '<code id="yaml" class="language-yaml"></code>';. This code replaces all the “children” of the pre tag with the new code block. Next, we get the code tag with id yaml.

JS

yaml.innerHTML = Prism.highlight(dockerCompose, Prism.languages.yaml, "yaml");

The main part of our code is actually what highlights our code. First, we pass the newly pasted yaml (stored in the dockerCompose variable). Next, we tell Prism what language to use with Prism.languages.yaml. Finally, we pass the language name which, in this case, is YAML. Then, we set this as the innerHTML of the code tag.

Note: The code in this project isn’t particularly clean as it’s mostly all in one file. I have done it this way to make the example a bit easier to follow when, in reality, you would most likely split it into multiple files.

Code

Try adding any sample YAML code in the widget below.

RELATED TAGS

prismjs
javascript
html
communitycreator
RELATED COURSES

View all Courses

Keep Exploring