Distinguish plain and relref Markdown links in render hook / .GetPage using relative permalink?

I’m experimenting with a render hook render-link.html that adds attributes to external links and resolves internal references to relative permalinks. If an internal reference points to a non-existing file then I raise a warning, and also if there is neither a path nor a fragment.

{{ $link := .Destination -}}                                                                                           
{{ $url := urls.Parse $link -}}                                                                                        
{{ $isRemote := ne $url.Scheme "" -}}                                                                                  
{{ if not $isRemote -}}                                                                                                
  {{ if $url.Path -}}                                                                                                  
    {{ $fragment := "" -}}                                                                                             
    {{ with $url.Fragment }}{{ $fragment = printf "#%s" . }}{{ end -}}                                                 
    {{ $page := .Page.GetPage $url.Path -}}                                                                            
    {{ if $page -}}                                                                                                    
      {{ $link = printf "%s%s" $page.RelPermalink $fragment -}}                                                        
    {{ else -}}                                                                                                        
      {{ warnf "Internal link in '%v' points to non-existing file: '%v'" .Page.File.Path $link -}}                     
    {{ end -}}                                                                                                         
  {{ else if not $url.Fragment -}}                                                                                     
    {{ warnf "Internal link without path and fragment encountered in '%v', URL: '%v'" .Page.File.Path $link -}}        
  {{ end -}}                                                                                                           
{{ end -}}                                                                                                             
<a href="{{ $link | safeURL }}"{{ with .Title }} title="{{ . }}"{{ end }}{{ if $isRemote }} target="_blank" rel="noopenr noreferrer"{{ end }}>{{ .Text | safeHTML }}</a>                                                                      
{{- /* whitespace control */ -}}                                                                                       

This is basically doing what I want, I can write plain Markdown links like [Label](page.md) and it gets transformed properly. However, in certain cases I would like to use the shortcode relref still. If I use it like this in a content file:

[Label]({{< relref "page" >}})

… then I run into the known HAHAHUGOSHORTCODE problem:

Internal link in ‘docs\_index.md’ points to non-existing file: ‘HAHAHUGOSHORTCODE-s0-HBHB’

So I changed it to the recommended:

[Label]({{% relref "page" %}})

The problem now is that relref translates the argument to /docs/page/ and the render hook receives this relative permalink, but .GetPage cannot fetch the corresponding page, leading to this warning:

Internal link in ‘docs\_index.md’ points to non-existing file: ‘/docs/page/’

I could remove the check whether .GetPage was successful but would thereby lose the validation for plain Markdown links. Is there any way to extend the validation to relref links or at least to ignore these links? Something like a pathExists function? A workaround to tell plain and relref links apart?

hard to be sure without the structure of your content directory. But what about {{% relref "/docs/page" %}} ? I would guess relref “page”` will look for a entry whose path is relative to the page from where the shortcode is invoked.

If you constantly use path relative to the content dir the you might switch .Page.GetPage to site.GetPage.