Page variables, render hooks, and goldmark.linkContext

I’m trying to add some simple (just css+html) tooltips to my site which show a page preview when hovering over internal links. I’ve tested it on list pages using the following code on layout/_default/section.html, and it’s working as expected:

        {{ range .Pages }}
        <li><span class="tooltip"><a href="{{.RelPermalink}}">{{.Title}}</a><span class="right bottom"><span class="tooltip-title">{{ with .Params.featured_image }}
  <figure class="title-image">
    <img src="{{ index . 0 }}" alt="">
  </figure>{{end}}{{.Title}}</span><br><span class="tooltip-excerpt">{{.Summary}}</span><i></i></span></span>
	</li>
        {{ end }}

But I’d like to apply this to all internal links on my site, not just on section pages.

Question 1: Is the render-link.html hook the correct place to do this?

Question 2: If so, can I call page variables there?

I tried adding some similar code to render-link.html, and it’ll tolerate added html elements (, , etc.) but can’t seem to handle variables like {{.summary}} or {{.Params.featured_image}}:

executing "_default/_markup/render-link.html" at <.Summary>: can't evaluate field Params in type goldmark.linkContext

Is it possible to use variables/params such as these within the render-link.html hook?

You need to access it via the .Page, which can be nil, so I suggest you do:

{{ with .Page }}
Summary: {{ .Summary }}
{{ end }}

Thanks for your help, bep.
Using your suggestion, I can get Hugo to serve the site without error, but I must still be making some grave errors, because:

  • {{with .Page}}{{.Title}} gives me the title of the current page, not the page I’m linking to;
  • and {{with .Page}}{{.Summary}} fails to pull any content at all

Here’s what I have for code in render-link.html:

{{ $link := .Destination }}
{{ $isRemote := strings.HasPrefix $link "http" }}
{{- if not $isRemote -}}
{{ $url := urls.Parse .Destination }}
{{- if $url.Path -}}
{{ $fragment := "" }}
{{- with $url.Fragment }}{{ $fragment = printf "#%s" . }}{{ end -}}
{{- with .Page.GetPage $url.Path }}{{ $link = printf "%s%s" .RelPermalink $fragment }}{{ end }}{{ end -}}
{{- end -}}
<span class="tooltip">
<a href="{{ $link | safeURL }}"{{with .Title}}{{.}}{{end}}
{{ if $isRemote }} rel="external" target="_blank" {{ end }}>{{ .Text | safeHTML }}</a><span class="right bottom"><span class="tooltip-title">{{with .Page}}{{.Title}}{{end}}</span><span class="tooltip-excerpt">{{with .Page}}{{.Summary}}{{end}}</span></span>
</span>

Yes, that is by design. There are some examples in the wild on how to find the page you link to.

Thanks for your help again.
I’ve managed to get 90% of what I needed using {{with .Page.GetPage .Destination}}. I’ll post what my render-link.html looks like below if its of any use to others (though I’m sure it’s a bit verbose).

The .tooltip/.tooltip-title/.tooltip-excerpt class elements create a css popover/tooltip showing page title, featured image, and summary when hovering over the link.

The one remaining puzzle I’m trying to figure out: I’d like this tooltip to target only internal links, but haven’t found a way to make that happen.
I’ll keep working on it.

{{ $isRemote := strings.HasPrefix $link "http" }}
{{- if not $isRemote -}}
{{ $url := urls.Parse .Destination }}
{{- if $url.Path -}}
{{ $fragment := "" }}
{{- with $url.Fragment }}{{ $fragment = printf "#%s" . }}{{ end -}}
{{- with .Page.GetPage $url.Path }}{{ $link = printf "%s%s" .RelPermalink $fragment }}{{ end }}{{ end -}}
{{- end -}}
<span class="tooltip">
<a href="{{ $link | safeURL }}"{{with .Title}}{{.}}{{end}}
{{ if $isRemote }} rel="external" target="_blank" {{ end }}>{{ .Text | safeHTML }}</a>
<span class="right bottom">
<span class="tooltip-title">{{ with .Page.GetPage .Destination}}{{.Title}}{{end}}</span>
<span class="tooltip-excerpt">
{{with .Page.GetPage .Destination}}
{{ with .Params.featured_image }}
<img class="title-image" src="{{ index . 0 }}" alt="">{{ end }}
{{ end }}
{{with .Page.GetPage .Destination}}{{.Summary}}{{end}}
</span>
</span>
</span>

May be you can play around (& adapt) this :
{{- if ne (slicestr .Destination 0 4) "http" }}

You should be able to use urls.Parse to pull out the Host.

1 Like

Thanks everyone.
Based on your advice (and bep’s advice from 2019), I was able to create two distinct variables ($external and $internal) and style them differently.
Probably a cleaner way to do it, but this works just fine for me.

{{if strings.HasPrefix .Destination "http" }}
{{ $external := .Destination }}

<a href="{{ $external | safeURL }}"{{with .Title}}{{.}}{{end}}>
{{ .Text | safeHTML }}</a>

{{end}}


{{ if not (strings.HasPrefix .Destination "http") }}
{{ $internal := urls.Parse .Destination}}
{{- if $internal.Path -}}
{{ $fragment := "" }}
{{- with $internal.Fragment }}{{ $fragment = printf "#%s" . }}{{ end -}}
{{- with .Page.GetPage $internal.Path }}{{ $internal = printf "%s%s" .RelPermalink $fragment }}
{{ end }}
{{ end -}}


<div class="tooltip">
<a href="{{ $internal | safeURL }}"{{with .Title}}{{.}}{{end}}>
{{ .Text | safeHTML }}</a>
<div class="right bottom">
<div class="tooltip-title">{{ with .Page.GetPage .Destination}}{{.Title}}{{end}}</div>
<div class="tooltip-excerpt">
{{with .Page.GetPage .Destination}}
{{ with .Params.featured_image }}
<figure><img class="title-image" src="{{ index . 0 }}" alt=""></figure>{{ end }}
{{ end }}
{{with .Page.GetPage .Destination}}{{.Summary}}{{end}}
</div>
</div>
</div>
{{- end -}}
1 Like

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