I am using highlight.js to render code snippets on this blog system. However, the official pack of highlight.js does not have Bicep as one of the languages. To add support for the Bicep language in highlight.js, you need to implement a Bicep language definition module. Below are the detailed steps and code examples.

Bicep Language Features


Bicep is a declarative, Azure-oriented Infrastructure-as-Code language. Its main features include:

  • Keywords: resource, module, param, var, output, targetScope, for, in, if, existing, import  
  • Types: string, int, bool, object, array, any  
  • Comments: // single-line comment, /* ... */ multi-line comment  
  • Strings: single quotes '...' and double quotes "..."

highlight.js Language Definition


The language definitions for highlight.js are usually as follows:

export default function(hljs) {
  return {
    name: 'Bicep',
    keywords: { ... },
    contains: [ ... ]
  };
}

You can refer to this example of the cmake language definition here: https://github.com/highlightjs/highlight.js/blob/main/src/languages/cmake.js

Let's create a file with name highlight.bicep.js

export default function (hljs) {
    return {
        name: 'Bicep',
        keywords: {
            keyword:
                'resource module param var output targetScope for in if existing import',
            type:
                'string int bool object array any',
            literal:
                'true false null'
        },
        contains: [
            hljs.COMMENT('//', '$'),
            hljs.COMMENT('/\\*', '\\*/'),
            {
                className: 'string',
                variants: [
                    hljs.QUOTE_STRING_MODE,
                    hljs.APOS_STRING_MODE
                ]
            },
            {
                className: 'number',
                begin: '\\b\\d+(\\.\\d+)?\\b'
            }
        ]
    };
}

Register Bicep Language and Example Usage


To register Bicep language, call hljs.registerLanguage('bicep', bicep) before rendering your code. 

import bicep from './highlight.bicep.js';

hljs.registerLanguage('bicep', bicep);
hljs.highlightAll();

You can refer to the official document here: https://highlightjs.readthedocs.io/en/latest/api.html#registerlanguage

In my case, my blog use a slightly complicated way to render code in my blog post. 

import bicep from '../3rd/highlight.bicep.js'

export function renderCodeHighlighter() {
    const pres = document.querySelectorAll('pre');
    pres.forEach(pre => {
        // Find <pre> that doesn't have a <code> inside it.
        if (!pre.querySelector('code')) {
            const code = document.createElement('code');
            while (pre.firstChild) {
                code.appendChild(pre.firstChild);
            }
            pre.appendChild(code);
        }

        // For code that can't be automatically detected, fall back to use XML
        if (pre.classList.contains('language-markup')) {
            pre.querySelector('code').classList.add('lang-xml');
        }
    });

    hljs.registerLanguage('bicep', bicep);

    const codeBlocks = document.querySelectorAll('pre code');
    codeBlocks.forEach(block => {
        hljs.highlightElement(block);
    });
}

That's all. Now we can test the example code:

<pre><code class="bicep">
param location string = resourceGroup().location
resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: 'mystorage'
  location: location
}
</code></pre>

If everything goes well, you will see this result:

param location string = resourceGroup().location
resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: 'mystorage'
  location: location
}