Hello, all! I’ve been enjoying getting a basic Hugo site set up for my personal worldbuilding wiki. The nature of the wiki is that I’ll often link to articles that don’t exist yet, but which I’m planning to create later on; this means that when I do get around to making that new article, I don’t have to go back and figure out everywhere I wanted it linked.
I’m trying to set up some way of automatically identifying these “dead” links and applying a class to them, so I can format them to look different than “live” links. I thought that using the render-link hook might be the answer, but it appears I can’t access the full range of functions there. Here’s what I’ve been trying (with some additional code for formatting external links):
{{ $live := false }}
{{ range .Site.RegularPages }}
{{ if eq .Params.destination .Destination }}
{{ $live = true }}
{{ end }}
{{ end }}
<a href="{{ .Destination | safeURL }}"{{ with .Title}}title="{{ . }}"{{ end }}
{{ if strings.HasPrefix .Destination "http" }}target="_blank" rel="noopener"{{ end }}
{{ if not $live }}class="dead"{{ end }}>
{{- .Text | safeHTML -}}{{ if strings.HasPrefix .Destination "http" }}<span class="material-icons"> </span>{{ end }}</a>
And the error I’m getting:
execute of template failed at <.Site.RegularPages>: can’t evaluate field Site in type goldmark.linkContext
Render hooks don’t receive .Site in context. Use either .Page.Site or (preferably) the site function.
But your render hook will get very expensive.
Take a site with 100 pages. You’re ranging through 100 pages for every link. With 10 links per page that’s 100x100x10 = 100,000 iterations. For a 1000 page site that would be 10,000,000 iterations.
I see. Right now my site is not particularly large, but I do want to create it in a sustainable way. Is there a different approach you’d recommend I look into? (By the way, I found your blog post on link and image render hooks when I was exploring this question–it was a bit over my head but what I could glean was very interesting!)
Yeah. If it were me I’d start with this, and then merge a class into the attributes map when the resource can’t be found. Keep the error/warning system as-is.
Thank you for the quick responses! I had found your blog post when I was exploring this question earlier, but it was a bit over my head. I’ll dig in deeper and see if I can figure out how to apply it for my purposes.
Thanks, I’m teaching myself from scratch (and very out of order) so it’s not trivial for me! At first attempt this is applying the “broken” format to all of my internal links regardless of if they’re broken or not. I’ll poke around a bit and see if I can figure out why.
Sure! Here is an example of markdown where I have both an internal link (to another article in the same section) and an external link (to Wikipedia). In the case of a dead link, this “mechanism.md” file wouldn’t yet exist.
In its [premature death throes](../mechanism) our sun has ballooned into a [red giant](https://en.wikipedia..org/wiki/Red_giant), cooling while increasing in size and brightness.
Removing the ../ from the internal links worked! I don’t remember exactly why I had them formatted that way, I’m sure it was some accumulation of newbie misunderstandings. Thank you for your patience.
For future reference, I studied @jmooring’s code and tried to incorporate what I learned in a way that felt more manageable for me as a beginner. I have a hangup about using code I don’t understand in my projects, even though I’m sure the original is much better! I expect this approach may need refinement, but here’s what I have working at the moment:
{{- $live := true -}}
{{- $url := urls.Parse .Destination }}
{{- if $url.IsAbs }}
{{- else}}
{{- with $.Page.GetPage $url.Path }}
{{- else }}
{{- $live = false }}
{{- end }}
{{- end }}
<a href="{{ (.Page.GetPage .Destination).RelPermalink | safeURL }}"{{ with .Title}}title="{{ . }}"{{ end }}
{{ if not $live }}class="dead" title="Coming soon!"{{ end }}
{{ if strings.HasPrefix .Destination "http" }}target="_blank" rel="noopener"{{ end }}>
{{- .Text | safeHTML -}}{{ if strings.HasPrefix .Destination "http" }}<span class="material-icons" style="font-size: 13px; vertical-align: middle; padding-left: 2px;"> </span>{{ end }}</a>