Hugo Tag Could

I recently started to look at migrating this blog from WordPress to a static site engine. Hugo got my attention and I decided to try it out. One thing I have in WordPress is a tag cloud. I couldn’t find an example of how to create one with varying font sizes in Hugo, so I tried creating my own. Hugo discussion forum topics Weighted tag cloud and Tag Cloud talk about this.

Hugo is written in Go and thus uses Go templates. Go is a language I haven’t written a single line of code in, but I looked at how the tag cloud is implemented in WordPress and tried to steal the logic, see the function wp_generate_tag_cloud. Here is what I came up with:

Update 2017-07-03: Code is updated to solve an issue that would cause a crash when all posts have the same number of tags (causing a division by 0). Thanks to @MunifTanjim in the Hugo discussion thread Weighted tag cloud.

Update 2017-07-27: Artem Sidorenko posted an improved version of this code where he uses logarithmic distribution for calculation of tag sizes. It doesn’t make a big difference with my current content, but clearly does on his, so maybe on yours too.

 1 {{- if gt (len .Site.Taxonomies.tags) 0 -}}
 2     {{- $fontUnit := "rem" -}}
 3     {{- $largestFontSize := 1.8 -}}
 4     {{- $smallestFontSize := 1.0 -}}
 5     {{- $fontSizeSpread := sub $largestFontSize $smallestFontSize -}}
 6     <!--<div>Font size unit: {{ $fontUnit }}</div>
 7     <div>Font min size: {{ $smallestFontSize }}</div>
 8     <div>Font max size: {{ $largestFontSize }}</div>
 9     <div>Font size spread: {{ $fontSizeSpread }}</div>-->
10 
11     {{- $maxCount := 1 -}}
12     <!--<div>Max tag count: {{ $maxCount }}</div>-->
13 
14     {{- $minCount := 1 -}}
15     <!--<div>Min tag count: {{ $minCount }}</div>-->
16 
17     {{- $countSpread := sub $maxCount $minCount -}}
18     <!--<div>Tag count spread: {{ $countSpread }}</div>-->
19 
20     {{- $.Scratch.Set "sizeStep" 0 -}}
21     {{- if gt $countSpread 0 -}}
22         {{- $.Scratch.Set "sizeStep" ( div $fontSizeSpread $countSpread ) -}}
23     {{- end -}}
24     {{- $sizeStep := ( $.Scratch.Get "sizeStep" ) -}}
25     <!--<div>Font step: {{ $sizeStep }}</div>-->
26 
27     <div class="widget">
28         <div class="widget-title">Tags</div>
29         <div class="tag-cloud-tags widget-content">
30         {{- range $name, $taxonomy := $.Site.Taxonomies.tags -}} 
31             {{- $currentTagCount := len $taxonomy.Pages -}}
32             {{- $currentFontSize := (add $smallestFontSize (mul (sub $currentTagCount $minCount) $sizeStep) ) -}}
33             <!--Current font size: {{$currentFontSize}}-->
34             <a href="{{ "/tags/" | relLangURL }}{{ $name | urlize }}" aria-label="{{ $name }} ({{$currentTagCount}} posts)" style="font-size:{{$currentFontSize}}{{$fontUnit}}">{{- $name -}}</a>
35         {{- end -}}
36         </div>
37     </div>
38 {{- end -}}

You can uncomment the commented lines for debugging. Also, if the tag keys instead of the tag names are rendered, set preserveTaxonomyNames = true in your config.toml or preserveTaxonomyNames: true in your config.yaml file. This took a while for me as a beginner to figure out.

No matching posts found. You can use wildcards and search only in titles, e.g. title:iot
Loading search index, please try again in a few seconds.
Index has completed downloading. Please search again.