Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create working Breadcrumbs for Hugo?

It's unbelievable how difficult is to find solid information about slightly more advanced techniques with Hugo.

After quite a while searching I’ve found this article with a very nice way to implement breadcrumbs for Hugo.

I modified it a little bit to not add an unnecessary link to the last trail and to make use of i18n to translate the URL segments into something more human-readable. I also made a small workaround to remove some unwanted trails that doesn't match a translated entry:

{{- $url := replace .Permalink ( printf "%s" ( "/" | absLangURL ) ) "" -}}
{{- $url := replace .Permalink ( printf "%s" ( "/" | absLangURL ) ) "" -}}
{{- $.Scratch.Add "path" ( "/" | absLangURL ) -}}

{{- $.Scratch.Add "breadcrumb" (slice (dict "url" ( "/" | absLangURL ) "name" "home" "position" 1 )) -}}
{{- range $index, $element := split $url "/" -}}
  {{- $.Scratch.Add "path" $element -}}
  {{- $.Scratch.Add "path" "/" -}}
  {{- if ne $element "" -}}
    {{- $.Scratch.Add "breadcrumb" (slice (dict "url" ($.Scratch.Get "path") "name" . "position" (add $index 2))) -}}
  {{- end -}}
{{- end -}}

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [{{ range $.Scratch.Get "breadcrumb" }}{{ if ne .position 1 }},{{ end }}{
        "@type": "ListItem",
        "position": {{ .position }},
        "item": {
          "@id": "{{ .url }}",
          "name": "{{ .name }}"
        }
    }{{ end }}]
}
</script>

<nav class="breadcrumb">
  {{- $length := len ($.Scratch.Get "breadcrumb") -}}

  {{- range $index, $.Scratch.Get "breadcrumb" -}}

    <!--
    Assigning a constant as default value for i18n function
    if it doesn't match any entry
    Then check if current Breadcrumb item matches this constant,
    which means that part shouldn't be one of Breadcrumb's trail
    -->
    {{- $i18n := i18n ( print "breadcrumbs-" .name ) | default "__INTERNAL__" -}}

    {{- if not ( eq ($i18n) "__INTERNAL__" ) -}}

      {{ if eq ( (int .position) ) $length }}
  <span class="breadcrumb-item active">{{ $i18n }}</span>
      {{- else -}}
  <a class="breadcrumb-item" href="{{ .url }}" >{{ $i18n }}</a>
      {{- end -}}

    {{- end -}}

  {{ end }}
</nav>

It works very nicely except that as far as I could notice so far while navigating through Pagination links everything starts duplicating N times as far as the Pagination Page increases (i.e twice of Page 2, thrice for Page 3 and so on).

I've searched even more and found a similar implementation in which there's no duplication... but the links are all messed up, the URL of each trail is a concatenation of all links of all trails o.O

I try to avoid asking things on Hugo's "forum" because the answers given there are most of the times hard to understand, incomplete or with "pseudo-pseudo-codes".

Does anyone know how to make this work and could lend me a hand?

like image 550
Bruno Augusto Avatar asked Mar 09 '23 05:03

Bruno Augusto


1 Answers

From the Hugo documentation and building on Lars's answer:

  1. Create a file named breadcrumbs.html in the folder layouts/partials of your Hugo project or theme
<ol  class="nav navbar-nav">
    {{ template "breadcrumbnav" (dict "p1" . "p2" .) }}
</ol>
{{ define "breadcrumbnav" }}
{{ if .p1.Parent }}
{{ template "breadcrumbnav" (dict "p1" .p1.Parent "p2" .p2 )  }}
{{ else if not .p1.IsHome }}
{{ template "breadcrumbnav" (dict "p1" .p1.Site.Home "p2" .p2 )  }}
{{ end }}
<li{{ if eq .p1 .p2 }} class="active"{{ end }}>
    <a href="{{ .p1.Permalink }}">{{ .p1.Title }}</a>
</li>
{{ end }}
  1. Include breadcrumbs.html where you need it with:
{{ partial "breadcrumbs.html" . }}

This produces links (including the sections) that are all valid.

like image 159
Ken Avatar answered Apr 25 '23 15:04

Ken