Example on multiple minor additional features to enhance Hugo’s default way of showing code.
Hugo’s default capabilities to show code are fairly good, it supports highlighting and multiple ways of showing code. However i was missing a copy to clipboard and showing the code modal features. They are not mandatory features but nice to have, and while we are at it why not add captions as well (something that is oddly missing form Hugo’s default shortcodes).
This article was written for Hugo 0.70.
Override the default highlight shortcode
The shortcode is an extended version of the default Hugo
highlight shortcode (
source). Overwriting the default shortcode is very simple, create a shortcode with the same name in your shortcode directory (/layouts/shortcodes/highlight.html) and you’re set.
Only the highlight shortcode is overwritten, not the markdown syntax “shortcode” because I only the use the former. You can override the markdown “shortcode”, if so desired.
Usage
The
default capabilities are still supported, in addition the following options were added. All options are optional, if none are provided the shortcode is identical to Hugo’s original shortcode.
option
effect
optional
default
title
adds a title to the code snippet
yes
caption
adds a caption to the code snippet
yes
attr
adds a source the code snippet
yes
attrlink
adds a source link to the code snippet. If attr is set it will be used as link text
yes
link
adds a link to the code snippet
yes
linkTarget
target for link
yes
_blank
linkTxt
sets the text for the link. Only applicable if link is set
yes
linkRel
sets the
rel attribute on the link. Only applicable if link is set
yes
noreferrer if not set and target is _blank
Unfortunately due to Hugo’s
limitations you cannot mix named (added by our shortcode) and unnamed parameters (used in the default shortcode). Therefore if you want to use the extended options you have to name the parameters from the default shortcode as well.
The shortcode is straight forward, if there are named parameters add a figcaption if required and otherwise have the same behavior as Hugo’s default shortcode.
The code is very similar to the overwritten highlight shortcode. It only supports named parameters. also notice htmlEscape which is required to handle the input as plain text.
<pre><code>{{ trim .Inner "\n" | htmlEscape | safeHTML }}</code></pre>
{{- if or (.Get "link") (or (.Get "attrlink") (or (or (.Get "title") (.Get "caption")) (.Get "attr"))) -}}
<figcaption>
{{- with (.Get "title") -}}
<h4>{{ . }}</h4>
{{- end -}}
{{- with (.Get "caption") -}}
<p>{{ . }}</p>
{{- end -}}
{{- if and (.Get "attr") (not (.Get "attrlink")) -}}
<p>Source: {{ (.Get "attr") | markdownify }}</p>
{{- end -}}
{{- with (.Get "attrlink") -}}
<p>Source: <ahref="{{ . }}"target="_blank"rel="noreferrer">{{ default . (($.Get "attr") | markdownify) }}</a></p>
{{- end -}}
{{- with (.Get "link") -}}
{{- $target := ($.Get "linkTarget") | default "_blank" -}}
<p>Link: <ahref="{{ . }}"target="{{ $target }}"rel="{{- with .Get "linkRel"}}{{.|plainify}}{{else}}{{ifeq$target"_blank"}}noreferrer{{end}}{{end-}}">{{ default . (($.Get "linkTxt") | markdownify) }}</a></p>
{{- end -}}
</figcaption>
{{- end -}}
The SCSS is the same as for the overwritten highlight shortcode with addition of limiting the height to force scrollbars on large snippets.
1
2
3
.pre-codepre {
max-height: 500px;
}
Code controls
Some simple features were added en enhance the UX. A copy (code) to clipboard button is added to each code snippet and because the height of the snippets is limited in the content a modal code overlay function was added as well.
The (fairly lightweight)
clipboardjs library is used to copy the code to clipboard. At the time of writing 2.0.6.
For the tooltips the
tooltips CSS library is used.
Usage
The controls are automatically added to each code snippet on the page, there are no options. This included Hugo’s default code shortcodes.
Code
First the HTML overlay is defined, it is very simple. The code-controls-template could also have been defined in Javascript but as explained the comment this approach was preferred over other solutions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<divid="code-container"class="markdown">
<divid="code-container-inner">
<divid="code-placeholder"></div>
</div>
<divid="close-code-overlay"></div>
</div>
{{/* Template for code controls. We can only use inline svg files in HTML, and i prefer to define HTML in HTML and not in JS anyway. */}}
<divid="code-controls-template"class="hidden code-expanded-controls">
<divtitle="Copy to clipboard"class="copy-to-clipboard">
{{ partial "inline-svg" "clipboard" }}
</div>
<divclass="hidden"aria-expanded="false"title="Close (ESC)">
{{ partial "inline-svg" "compress-alt" }}
</div>
<divaria-expanded="false"title="Expand">
{{ partial "inline-svg" "expand-alt" }}
</div>
</div>
Javascript is used to inject the code controls into every code snippet and wire up the events. First get the control template and prepare it to be inserted (copied) into other controls. Go through all highlight code snippets and insert the code controls, the same applies for the regular code snippets but they have to be filtered first to only include actual code snippets and not just single words/sentences. Due to how the CSS rules are set-up regular code snippets have to be wrapped before the controls can be added. If at least one “code control” element was inserted in the page the clipboardjs library is initialized. Because the copy to clipboard buttons do not contain the to-be-copied-content (inner text) the text function is overwritten to point to the corresponding code element. Finally a tooltip is shown if the code/text was copied to clipboard to inform the user. To show the code modal the HTML elements containing the code are copied to the HTML overlay element which is made visible.
License: The text and content is licensed under CC BY-NC-SA 4.0.
All source code I wrote on this page is licensed under The Unlicense; do as you please, I'm not liable nor provide warranty.
Noticed an error in this post? Corrections are
spam.appreciated.