Vue.js Syntax Highlighting with highlight.js
Everyone loves a good syntax highlighting. This post explains how to use highlight.js
for syntax highlighting in a Vue.js application. The method shown here allows syntax highlighting both on original creation of an element
as well as on updates to the source-code, using a simple v-highlightjs
directive such as this:
<pre v-highlightjs><code class="javascript"></code></pre>
You can see a live example here: jsfiddle.net/metachris/1vz9oobc.
To achieve this, we just need to install the highlight.js
dependency and create a custom highlightjs
directive. Let’s dive straight in!
Note: The code from this post is now also published as npm package vue-highlightjs, which you can easily use in your project.
Install the highlight.js dependency
The first step is to install highlight.js
as a dependency with the npm
node package manager:
$ npm install --save highlight.js
Include the highlight.js CSS file in your HTML
To reference the highlight.js CSS style sheet from the HTML, just include a <link rel="stylesheet"
tag which points to
either a downloaded highlight.css
file or to their CDN URL:
<!-- Downloaded and saved in /static/css/highlight.css -->
<link rel="stylesheet" href="/static/css/highlight.css">
<!-- Or if you want to use the stylesheet from the CDN -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/styles/default.min.css">
highlight.js comes with a number of different styles, which are defined by using a specific stylesheet for each style (we are using the default style here). For other available styles look into the highlight.js styles directory (and don’t forget to add “.min” before “.css”).
A custom Vue.js directive: v-highlightjs
To use highlight.js
from within Vue.js components, we are going to create a custom Vue.js directive
called highlightjs
. You can declare this directive directly in your main.js
file:
import Vue from 'vue'
import hljs from 'highlight.js'
...
Vue.directive('highlightjs', {
deep: true,
bind: function (el, binding) {
// on first bind, highlight all targets
let targets = el.querySelectorAll('code')
targets.forEach((target) => {
// if a value is directly assigned to the directive, use this
// instead of the element content.
if (binding.value) {
target.textContent = binding.value
}
hljs.highlightBlock(target)
})
},
componentUpdated: function (el, binding) {
// after an update, re-fill the content and then highlight
let targets = el.querySelectorAll('code')
targets.forEach((target) => {
if (binding.value) {
target.textContent = binding.value
hljs.highlightBlock(target)
}
})
}
})
(You can also use the npm package vue-highlightjs
instead of declaring the directive manually.)
Using v-highlightjs
To highlight code (for example JavaScript) which is either hardcoded in a template or stored in a variable (or getter) called sourcecode
, we can use the v-highlightjs
directive like this:
<pre v-highlightjs><code class="javascript">{{ sourcecode }}</code></pre>
Reacting to code updates
highlight.js
replaces the content of the <code> block. If using the directive as shown above, updating the source-code after the initial highlighting does not work anymore. To be able to update the code and highlight it again after an update, pass the variable directly into the v-highlightjs
directive like this:
<pre v-highlightjs="sourcecode"><code class="javascript"></code></pre>
Live Example
References
- highlight.js
- Vue.js / Custom Directives
- Live demo: jsfiddle.net/metachris/1vz9oobc
- npm package
vue-highlightjs
– you can use this package instead of manually declaring thev-highlightjs
directive and importinghighlight.js
You can reach out to me via @metachris. Please let me know if you have any feedback or suggestions!