Siblings, children, related & content links

For a hierarchical documentation site (tree structure), I’m looking to create automated navigations. I have directories and a _index.md page in each one.

On each page, I list child pages and siblings. In pseudo code, I have something like this.

A list of subpages in the content:

{{ with .Pages }}
  {{ range . }}
    ...

and a list of siblings pages underneath

{{ with .Parent }}
  {{ range .Pages }}
    ...

So far, so trivial and works perfectly.

Next, I add some related. But I don’t want a link in related that’s already in subpages or siblings. So I do something like this (here for siblings):

{{ $related := .Site.RegularPages.Related . }}
{{ $related = complement .Parent.Pages $related | first 5 }}

{{ with $related }}
  {{ range . }}

Of course, I add conditions to display nothing if the list of related is null. I won’t elaborate here.

Now: the hard question (for me)! Knowing that all links in the body of the article are made with {{ relref }} or {{ ref }}, I’d like to:

  • list all the links in the article and
  • create a slice

Then I could make a complement to remove them from all the links in the children, siblings or related sections. This way, the same link would never appear twice on the page.

I’m interested in any suggestions you may have for creating a collection from markdown content.

Subsidiary question. Is it possible to use absolute or relative links in pure Markdown to generalize the tool?

  • [About](/site/about/)
  • [About](about)
  • [About](https://mysite.com/site/about/)

Thanks for your feedback and advice

Starting with the embedded link render hook, create your own render hook that appends the link’s page reference to a Page.Store slice. When accessing the slice later on, pass it through the uniq function to remove duplicates (i.e., when the page includes two links to the same destination).

Yes, if you base your link render hook on Hugo’s embedded link render hook as described above.

With this content structure:

content/
├── site/
│   ├── about.md
│   └── foo.md
└── _index.md

And this markdown in content/site/foo.md:

- [About](/site/about/)
- [About](about)
- [About](./about)
- [About](../site/about)
- [About](https://mysite.com/site/about/)

All of the links above work.

1 Like

Also, from the link render hook documentation…

The embedded link render hook resolves internal Markdown destinations by looking for a matching page, falling back to a matching page resource, then falling back to a matching global resource. Remote destinations are passed through, and the render hook will not throw an error or warning if unable to resolve a destination.

I would probably modify the render hook to throw an error or warning when unable to resolve a destination. And I would probably continue to ignore (pass through) remote destinations as described above.

1 Like

Thank you so much Joe!

The solution isn’t quite clean yet, but it’s functional.

I added a single line to render-link.html:

{{ page.Store.SetInMap “links” $href .Text }}

Then I can iterate, etc. on my templates, with something like, or work with collections:

{{ range $k, $v := .Store.Get “links” }}
  {{ $k }}
{{ end }}

As I’m not using key-values, it must be possible to make things simpler, but that’s for later.

Thanks for the comments on uniq and link validation, but I won’t even need them. I’m never going to display the .Store list.

Basically, I’ll just remove a link from siblings, children or related if it’s in the .Store list. Since the sibling, child or related links are still valid, there’s no risk.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.