How-To add cross reference in Hugo markdown links avatar
Yohan Yukiya Sese-Cuneta
 | | 4 minutes read | Update at

Fediverse Follow

One of the less commonly used feature of Hugo is render hooks. In this post, we are going to use render hooks to add internal cross reference support to Markdown’s default way of creating links: [text](https://example.com#fragment "Title").

Internal cross references in Hugo is usually done by using the built-in shortcodes {{< ref >}} or {{% relref %}} but did you know since Hugo v0.62.0 1 the advisable method is to use render hooks 2?

Features

  • Use regular Markdown link format to cross reference within Hugo
    • {{< ref >}} and {{% relref %}}, or any variation thereof, is a thing of the past
    • Automatically use the content’s title
    • Multilingual support
    • Markdown link text and title support
    • With URI fragment support

What’s new

  • 2022-06-17:

    • fix: [text](./path/to/content/) and [text.ext](./path/to/file.ext) formats
  • 2022-05-27:

    • [text](./path/to/content/)
    • [text.ext](./path/to/file.ext)
    • reorganized the How To Use section

Steps

  1. Create a file called render-link.html in this directory /layouts/_default/_markup/

  2. Add the code below:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    {{- $baseurl := urls.Parse site.BaseURL -}}
    {{- $url := urls.Parse .Destination -}}
    {{- $getpage := site.GetPage .Destination -}}
    {{- $internal := lt (len $url.Host) 1 -}} {{/* NOTE: internal links will always have an empty $url.Host */}}
    
    {{- $fragment := $url.Fragment -}}
    {{- with $fragment -}}{{ $fragment = printf "#%s" $fragment }}{{- end -}}
    
    {{- $destination := "" -}}
    {{- if $internal -}}
      {{- if (strings.HasPrefix $url.Path "./") -}}
        {{/* NOTE: for links starting with ./ */}}
        {{- $urltrimmed := strings.TrimPrefix "./" $url -}}
        {{- $destination = printf "%s://%s/%s%s" $baseurl.Scheme $baseurl.Host $urltrimmed $fragment -}}
      {{- else -}}
        {{/* NOTE: for internal links */}}
        {{- $destination = printf "%s%s" $getpage.RelPermalink $fragment -}}
      {{- end -}}
    {{- else -}}
      {{- $destination = .Destination -}}
    {{- end -}}
    
    <a href="{{ $destination | safeURL }}"{{ with or .Title $getpage.LinkTitle .Text }} title="{{ . }}"{{ end }}{{ if not $internal }} rel="noopener external"{{ end }}>{{ or .Text .Title $getpage.LinkTitle | safeHTML }}</a>
    

That’s it.

How to use

Traditional

1
2
3
4
- [https://example.com/#fragment](https://example.com/#fragment "https://example.com/#fragment")
- [direct](https://im.youronly.one/techmagus/browser-wars-3-blink-gecko-2018344/ "Title")
- [direct with #fragment](https://im.youronly.one/techmagus/browser-wars-3-blink-gecko-2018344/#fragment "Title")
- [#fragment only](#fragment)

New

Special

The [text](./path/to/content/) format is useful when you want to create a link to another part of your website, under the same (sub)-domain but not part of the current Hugo project. This format will not generate an external link icon if the How-To add link icons in Hugo markdown links is also installed.

The [text.ext](./path/to/file.ext) is useful for download links hosted under the same (sub)-domain, within or external relative to the current Hugo project.

1
2
- [send a gift](./p/gift/)
- [link-icons.7z](./techmagus/dls/link-icons.7z)

Without a file extension

1
2
3
4
5
6
7
8
- [](20181210-browser-wars-iii)
- [](/20181210-browser-wars-iii)
- [](20181210-browser-wars-iii "Title")
- [](/20181210-browser-wars-iii "Title")
- [Text](20181210-browser-wars-iii)
- [Text](/20181210-browser-wars-iii)
- [Text](20181210-browser-wars-iii "Title")
- [Text](/20181210-browser-wars-iii "Title")

With file extension

1
2
3
4
5
6
7
8
- [](20181210-browser-wars-iii.md#fragment)
- [](/20181210-browser-wars-iii.md#fragment)
- [](20181210-browser-wars-iii.md#fragment "Title")
- [](/20181210-browser-wars-iii.md#fragment "Title")
- [Text#fragment](20181210-browser-wars-iii.md#fragment)
- [Text#fragment](/20181210-browser-wars-iii.md#fragment)
- [Text#fragment](20181210-browser-wars-iii.md#fragment "Title")
- [Text#fragment](/20181210-browser-wars-iii.md#fragment "Title")

Not supported

Internal linking without a file extension and with a #fragment produces a wrong link.

1
2
3
4
5
6
7
8
- [](20181210-browser-wars-iii#fragment)
- [](/20181210-browser-wars-iii#fragment)
- [](20181210-browser-wars-iii#fragment "Title")
- [](/20181210-browser-wars-iii#fragment "Title")
- [Text#fragment](20181210-browser-wars-iii#fragment)
- [Text#fragment](/20181210-browser-wars-iii#fragment)
- [Text#fragment](20181210-browser-wars-iii#fragment "Title")
- [Text#fragment](/20181210-browser-wars-iii#fragment "Title")

Also take note of the following formats.

1
2
- [link-icons.7z](/dls/link-icons.7z)
- [link-icons.7z](../../dls/link-icons.7z)

Instead of the above, use [text](./path/to/file.ext) like so [link-icons.7z](./techmagus/dls/link-icons.7z) will render as: link-icons.7z

Improve it

Feel free to improve the code above and share back to the community. Please provide your website and name so you will be properly credited.


Did you like it? Do share this post, leave a comment below, and send me a gift! (opens in a new tab/window)

avatar

Yohan Yukiya Sese-Cunetaㆍ사요한・謝雪矢·ᜌᜓᜃᜒIf this is not the end of oblivion, then I shall live everyday as if my life were to end this very day.

The YOOki Chronicles

The YOOki Chronicles is Yohan Yukiya Sese-Cuneta’s return into casual and personal blogging. The name “YOOki” is a mash-up of the acronym of YourOnly.One and my nickname ᜌᜓᜃᜒ (Yuki・雪矢).

Interestingly, according to Chinese legend, (YOO) is an ancient Chinese surname. The ancestors of the surname were closely linked with the ancient sage-king named Yu Shun. In Korea, the (YU) lineage traces to the Xia, Han, and Joseon dynasties. Holders of the surname Yu or Yoo had a reputation for charity and diligence.1

It is also the word for “willow” or the “willow tree” which means graceful or slender; and a tree growing near a body of water which provide continuous nourishment and resources for everyone. It can also mean to exist, an oil (anointment(?)), and simply as “U” (you).

The Hanzi (ki) character means to record, be disciplined, provide order. While the Hangeul equivalent, (ki), means energy, spirit, a banner, and a period of time; and is also a suffix used to make a gerund or an infinitive.

Now Playing
Social Links