Section Depth

I have the following directory structure:

.
├── _index.md
├── policy.md
├── contact
│   ├── _index.md
│   ├── thanks.md
├── disclaimer.md
├── consulting
│   ├── _index.md
│   └── strategy.md
├── mission.md
├── services
│   ├── _index.md
│   ├── webdevelopment.md
│   ├── apps.md
│   └── design.md
└── privacy.md

I need to access the “section” depth. Example:

.
├── _index.md <=== 0
├── policy.md
├── contact <=== 1
│   ├── _index.md 
│   ├── thanks.md
├── disclaimer.md
├── consulting <=== 1
│   ├── _index.md  
│   └── strategy.md
├── mission.md
├── services <=== 1
│   ├── _index.md <=== 1
│   ├── webdevelopment.md <=== 2
│   ├── apps.md <=== 2
│   └── design.md <=== 2
└── privacy.md

What would be a easy way to achieve this? Currently I’m thinking of using urls.Parse and counting the slashes (/), but that seems unnecessarily complex. Any help would be greatly appriciated.

Edit: I forgot to mention. I’m using the breadcrumb example. So expected output for services would be: 1. Home / 2. Services / 3. Webdevelopment.

Use add, e.g.:

{{ $level := add .level 1 }}
{{ template "breadcrumbnav" (dict "p1" .p1.Site.Home "p2" .p2 "level" $level )  }}

Thanks for your reply Bep.

I’m getting the following error:

Failed to render pages: render of "page" failed: execute of template failed: template: _default/single.html:9:7: executing "_default/single.html" at <partial "structuredData/breadcrumb.html" .>: error calling partial: ".../layouts/partials/structuredData/breadcrumb.html:1:17": execute of template failed: template: partials/structuredData/breadcrumb.html:1:17: executing "partials/structuredData/breadcrumb.html" at <.level>: can't evaluate field level in type *hugolib.pageState

I’ve managed to get it to work by using {{ $level := 3 }} and {{ template "sd-breadcrumb" (dict "p1" .p1.Parent "p2" .p2 "level" (add .level 1)) }}. However, this is the exact inverse of what I would like to have happen.

The result of the above is 3. Home / 2. Services / 1. Webdevelopment.. To fix this I can do {{ template "sd-breadcrumb" (dict "p1" .p1.Parent "p2" .p2 "level" (add .level -1)) }} and give $level a default value of e.g. 3. But this will break when I have a breadcrumb with a depth of not 3.

So I still need to obtain the current page depth somehow.

Any help would be greatly appriciated.

If you use a HTML ol list to generate your breadcrumb, your depth is automagically generated!

And ol is a valid choice: https://www.w3.org/TR/wai-aria-practices-1.1/examples/breadcrumb/index.html

Thanks for your reply @.

That’s a cute workaround. But my issue above was just as an example. My “real-world” application for this is to implement Breadcrumbs as Structured Data which have a position as a required property.

Thanks for your suggestion though.

My code currently, looks like this:

{{ $level := 3 }}

{{ if not .IsHome }}
    <script type="application/ld+json">
        {
            "@context": "https://schema.org",
            "@type": "BreadcrumbList",
            "itemListElement": [
                {{ template "sd-breadcrumb" (dict "p1" . "p2" . "level" $level) }}
            ]
        }
    </script>

{{ end }}

{{ define "sd-breadcrumb" }}
    {{ if .p1.Parent }}
        {{ template "sd-breadcrumb" (dict "p1" .p1.Parent "p2" .p2 "level" (add .level -1))  }}
    {{ else if not .p1.IsHome }}
        {{ template "sd-breadcrumb" (dict "p1" .p1.Site.Home "p2" .p2 "level" (add .level -1))  }}
    {{ end }}
        {
        "@type": "ListItem",
        "position": {{ .level }},
        "name": {{ .p1.Title }},
        "item": {{ .p1.Permalink }}
        },
{{ end }}

So a quick’n dirty answer:

{{ define "breadcrumbs" }}
{{ $position := ( sub .position 1 ) }}
{{ with .context.Parent }},
{
"@type": "ListItem",
"position": {{ $position }},
"item": {
"@id": {{ .Permalink }},
"name": {{ .Title }}
}
}
{{ template "breadcrumbs" ( dict "context" . "position" $position ) }}
{{ end }}
{{ end }}

{{ $position := 0 }}
<script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "BreadcrumbList",
      "itemListElement": 
      [{
        "@type": "ListItem",
        "position": {{ $position }},
        "item": {
          "@id": {{ .Permalink }},
          "name": {{ .Title }}
        }
    }
        {{ template "breadcrumbs" ( dict "context" . "position" $position ) }}
      ]
    }
</script>

This file is partials/ld-breadcrumb.html, called by {{ partial "ld-breadcrumb.html" . }}.

Wow. That seems to work @nfriedli! The only thing I changed was {{ $position := ( sub .position 1 ) }} to {{ $position := ( add .position 1 ) }}. Furthermore, I assumed the order mattered (ie: position 1 at index 0 in the array) but the rich snippet testing tool isn’t complaining about it.

Thank you very much!

It’s a wild hack, but I’ll mark it as a solution.

1 Like

Hmm. Yeah. If An array of breadcrumbs listed in a specific order. is a requirement your solution is indeed invalid. Weird that somehow the testing tool sees it as valid structured data.

Edit: @bep Would you be open for a pull request implementing a .Page.Depth attribute?

I have another solution. Only in my head…

  1. Build a slice with absolute permalinks. Current page, mother page, grand mother page, etc.
  2. Sort the slice. The shorter permalink is in position 1, etc. (NB: slice length give you the depth…)
  3. Range the slice to create your ld+json with a position increment.

I’ll try to code that today.