Introduction
You can config Hugo to generate highlighted code blocks with Chroma. This post records my experience of switching from highlight.js
to Chroma, and implementation of some popular code block features such as adding filename as titles.
You can find the complete Hugo documentation here.
Preview
This markdown
```html {path="layouts/partials/head.html", hl_lines="2-4"}
<head>
<meta name="author" content="{{ with .Site.Params.author }}{{ . }}{{ end }}" />
<meta name="description" content="{{if .IsHome }}{{ $.Site.Params.description }}{{ else }}{{ .Description }}{{ end }}" />
<meta name="theme-color" content="#111111" />
</head>
```
is rendered as
|
|
The block will expand horizontally on hover when the media width is at least 1600px
.
Chroma Setup
Chroma is enabled by default, so we can start highlighting codes by either specifying one of the languages Chroma supports in the markdown:
```javascript
function addOne(number) {
return number + 1;
}
```
or by using the built-in highlight
shortcode:
{{< highlight javascript >}}
function addOne(number) {
return number + 1;
}
{{< /highlight >}}
Using custom CSS
There are many Chroma styles you can choose from, and you can just specify the styles with config parameter markup.highlight.style
.
|
|
You can also use custom stylesheet by turning off the inline CSS feature:
|
|
and providing your own CSS file, such as the github-dark theme.
Inline options
You can add inline parameters to code blocks. For example, both markdown blocks:
```javascript {linenos=inline, hl_lines="1 4-6"}
function addOne(number) {
return number + 1;
}
function addTwo(number) {
return number + 2;
}
```
{{< highlight javascript "linenos=inline, hl_lines=1 4-6" >}}
function addOne(number) {
return number + 1;
}
function addTwo(number) {
return number + 2;
}
{{< /highlight >}}
render as follows.
1function addOne(number) {
2 return number + 1;
3}
4function addTwo(number) {
5 return number + 2;
6}
For the full list of options, visit the Hugo documentation.
Additional Features
Adding titles
The usual approach to add a custom title to a code block is to write a separate shortcode above the code fence.
{{< path "/src/lib/util.js" >}}
```javascript
function addOne(number) {
return number + 1;
}
```
This is rather cumbersome, so I added a custom markdown render hook so that the path can be specified within the inline option.
|
|
Explanation
When the markdown is parsed, all valid option parameters are stored in .Options
, and the additional parameters are stored in .Attributes
and attached as HTML attributes. So if linenos=table, path="path/to/file"
is passed as option, we will have
{{ .Attributes := dict "path" "path/to/file" }}
{{ .Options := dict "linenos" "table" }}
and the code block will be rendered as:
<div class="highlight" path="path/to/file">
<pre tabindex="0" class="chroma">
<!-- code with line numbers -->
</pre>
</div>
My strategy is to check if the path
key from the map of attributes, and then add a <div class="code-path">
element that contains its value. Ideally, .Attributes
need to be fed into the highlighter as well, but I am currently not using custom attributes in my code fences, and manipulating maps in Hugo is still a painful process.
This custom template allows us to provide a path
option in code fences. For example, the source code for the code block above looks like this.
```html {path="layouts/_default/_markup/render-codeblock.html"}
<div class="code-container">
...
</div>
```