Motivation
When I first made my Hugo website, one of the very first things I wanted to do was add a “copy to clipboard” button next to important snippets. My theme came with a copy button for multi-line code snippets, but there was nothing available for inline code like this
, i.e. the <code>
HTML tag. It was pretty important for me to make how-to guides that were as simple and easy to follow as possible, and this was a feature that seemed worth the time to figure out.
Outcome
Create a copy to clipboard button for code like this
Copy to clipboard
.
The above line is written like this in the markdown.
1
| Create a copy to clipboard button for {{% copy-to-clipboard id="example" %}}`code like this`{{% /copy-to-clipboard %}}.
|
You can see a live example in this post.
Solution
Note
I’m not a Hugo expert, nor an HTML, CSS, or JavaScript expert. All of these things I have only dabbled in. There is likely a better way to organize this or achieve this. I will show you how I accomplished it and hopefully you can improve it from there.
1. Create the JavaScript and CSS files
The first step is to create a JavaScript file and create a function that will take in an element id, and then copy the text in that element to the clipboard.
Create static/copy-to-clipboard.js
with the following contents.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| /*
* Some methods for copying to the clipboard and updating a tooltip.
*/
function copyToClipboard(textElementId, tooltipId) {
element = document.getElementById(textElementId);
const copyText = element.textContent;
navigator.clipboard.writeText(copyText);
var tooltip = document.getElementById(tooltipId);
tooltip.innerHTML = "Copied: " + copyText;
}
function tooltipReset(tooltipId) {
var tooltip = document.getElementById(tooltipId);
tooltip.innerHTML = "Copy to clipboard";
}
|
Create static/tooltip.css
with the following contents.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| .tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 140px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 150%;
left: 50%;
margin-left: -75px;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
|
2. Include the files with the base layout html
Note
If you don’t already have a layouts/_default/baseof.html
file, your theme should. You can copy the contents of that file to this location to override the theme layout, then add the lines mentioned.
In layouts/_default/baseof.html
add the following to the <head>
section
1
2
| <script src="/copy-to-clipboard.js" async></script>
<link rel="stylesheet" href="/tooltip.css">
|
3. Create the Hugo shortcode to use in markdown
Create the shortcode by creating a file layouts/shortcodes/copy-to-clipboard.html
1
2
3
4
5
6
7
8
9
10
11
12
| <span id="{{.Get `id`}}-text">
{{.Inner}}
</span>
<span class="tooltip">
<span class="tooltiptext" id="{{.Get `id`}}-tooltip">
Copy to clipboard
</span>
<i class="fa fa-clipboard" style="font-size:12px; cursor:pointer;"
onclick="copyToClipboard('{{.Get `id`}}-text', '{{.Get `id`}}-tooltip')"
onmouseout="tooltipReset('{{.Get `id`}}-tooltip')">
</i>
</span>
|
This is the part that will allow you to wrap any text in a markdown file like so
1
| {{% copy-to-clipboard id="some-id" %}}my text to copy{{% /copy-to-clipboard %}}
|
You can use markdown or HTML to format the text if necessary, such as adding code tags. The JavaScript should select only the visible text to copy to the clipboard (i.e. not the markdown formatting).