Code Syntax Highlighting for Prismic in Vue & Nuxt
Learn how to implement a Code Syntax Highlighter using highlight.js for your preformatted data from Prismic, including a language selector.
You should be familiar with the basic concepts of Prismic. If not, get started reading the Prismic Docs.
Prepare CMS
To achieve our goal, we will create a Slice in Prismic. We could also achieve Code Highlighting without using Slices. The drawback would be, that you would rely on automatic language detection, which can fail easily. We will use a list of languages to select from for each code block using Slices. This will improve flexibility and modularity.
Learn more about Slices and how to use them.
Create Slice
In this example, the Slice will be named CodeBlock
. Just add a new Slice into your Slice library or any document you will use it. It's up to you if you implement the Slice in the Prismic Dashboard or in the local Slice Machine.
Slice content
First, add a Select field called language
to your Slice and add the languages you need for the Code Highlighting into the options. Define one language per line and check the "Define first value as default" field.
Secondly, add a Rich Text field called preformatted
, which has preformatted as the only active format option.
The Slice content should look like the following:
Prepare Frontend
I assume, that you have already integrated Prismic into your Frontend. If not, check out Get Started with Vue or Get Started with Nuxt.
For the implementation in the Frontend, you will need to create the Slice, add highlight.js and use a custom HTML Serializer to highlight the code.
Create Slice
We will use the Prismic Rich Text Component to render the preformatted Rich Text field we defined in the CMS.
<template>
<PrismicRichText
:field="slice.primary.rich_text"
/>
</template>
<script>
export default {
props: {
slice: {
type: Object,
required: true
}
}
};
</script>
Add highlight.js
To Syntax Highlight the code, we will need to install highlight.js.
npm i highlight.js
Then, you need to register all languages, you have already defined in your Slice. Import and register each language manually with hljs.registerLanguage()
method. Check the list of all supported languages with its aliases for the import.
The first argument of hljs.registerLanguage()
should reflect the exact name of the language you defined in the Select Field in your CMS, as we will use it directly to identify the language.
<script>
import hljs from 'highlight.js/lib/core';
import bash from 'highlight.js/lib/languages/bash';
import javascript from 'highlight.js/lib/languages/javascript';
import xml from 'highlight.js/lib/languages/xml';
import json from 'highlight.js/lib/languages/json';
hljs.registerLanguage('bash', bash);
hljs.registerLanguage('vue', xml);
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('json', json);
export default {
props: {
slice: {
type: Object,
required: true
}
}
};
</script>
Unfortunately, there is no language support for Vue in highlight.js. Use XML as seen in the example to get Code Highlighting for Vue.
Custom HTML Serializer
The last step is to customize the HTML output with Syntax Code Highlighting. We will create a method called htmlSerializer
and pass it to the html-serializer
Prop in the <PrismicRichText />
Component to override the default HTML Serializer.
Our custom HTML Serializer will check for the preformatted element in the Rich Text field and use the hljs.highlight()
method to highlight the code. The method takes an input and an object for the options as arguments. In the options, we will pass the language
field from the Slice data.
You can read more about highlight.js usage.
Here, you can read about all accessible arguments for the htmlSerializer()
method.
<template>
<PrismicRichText
:field="slice.primary.rich_text"
:html-serializer="htmlSerializer"
/>
</template>
<script>
import { Element as Elements } from '@prismicio/helpers';
import hljs from 'highlight.js/lib/core';
import bash from 'highlight.js/lib/languages/bash';
import javascript from 'highlight.js/lib/languages/javascript';
import xml from 'highlight.js/lib/languages/xml';
import json from 'highlight.js/lib/languages/json';
hljs.registerLanguage('bash', bash);
hljs.registerLanguage('vue', xml);
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('json', json);
export default {
props: {
slice: {
type: Object,
required: true
}
},
methods: {
htmlSerializer(type, element, content, children) {
if (type === Elements.preformatted) {
this.text = element.text;
return `<pre>${
hljs.highlight(
element.text,
{ language: this.slice.primary.language }
).value
}</pre>`;
}
}
}
};
</script>
Themes
Don't forget to include a theme to see any results.
There is a list of all themes in action. The import names/source for all themes can be found here.
Conclusion
Now, you can customize your Slice for your needs and add additional features like a copy code button.
The concepts for Vue or Nuxt you just saw can be easily translated to any other Frontend using Prismic as CMS. You just need a customized HTML Serizalizer and highlight.js to highlight the code for preformatted Rich Text fields.