Proste wewnętrzne ref-linki w Hugo

tech • 476 słów • 3 minuty czytania

Gdy w jednej notatce potrzeba się odwołać do innego wpisu wystarczy użyć zwykłego odnośnika. W takim WordPress-ie nie było żadnego mechanizmu i dodawało się po prostu zwykły link do podstrony z wpisem (bezwzględny w domyśle). Podobnie mógłbym robić na stronie generowanej w Hugo, ale to mi się nie podoba…

Nie chcę w plikach z treściami bezwzględnych linków do wewnętrznych elementów strony - preferuję relatywne względem roota strony. Nie chcę też sztywnych adresów, bo jak zmienię nazwę, sluga bądź format generowanych adresów to wszystko się rozjedzie. I trzeba będzie przeszukiwać i modyfikować Markdown-y.

Na szczęście Hugo posiada do tego celu specjalne shortcodes - ref, relref. Nie trzeba jawnie podawać adresu w odnośniku [#1], wystarczy skorzystać z kodu [#2], aby w wynikowym HTML-u otrzymać poprawny link do podstrony.

[Hello Wordl!](/2006/hello-world.html)							#1
[Hello Wordl!]({{< relref "2006-01-15-hello-world" >}})			#2
[Hello Wordl!](ref:2006-01-15-hello-world)						#3

Niby fajnie, ale ja chcę też w treściach minimalizować zewnętrzne i niestandardowe wstawki, najlepiej czysta treść z czystym Markdownem. Idealnym rozwiązaniem byłoby móc zdefiniować linka do innej podstrony za pomocą dedykowanego protokołu lub przedrostka ref [#3]. I o dziwo da się to łatwo uzyskać w Hugo!

Z pomocą przychodzą Markdown Render Hooks, wprowadzone jakiś czas temu w Hugo. Można nimi wpływać na kod wynikowy generowany z niektórych elementów Markdowna. Dotyczy to także odnośników.

Mój szablonowy plik z kodem “render-hooka” linków (_default/_markup/render-link.html) ze wsparciem zaproponowanego wyżej formatu cross-linkowania stron z przedrostkiem “ref” wygląda tak:

{{- $dest := .Destination -}}

{{- if strings.HasPrefix $dest "ref:" -}}
	{{- $dest = relref .Page (substr $dest 4) -}}
{{- end -}}

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

Treść chyba nie wymaga szerszego komentarza. Przed wygenerowaniem kodu HTML-a z linkiem, sprawdzany jest podany adres pod kątem prefiksu ref:. Jeśli string zaczyna się od niego to dalsza jego część traktowana jest jako nazwa (identyfikator) i rozwijana przez funkcję relref (tą samą co używają adekwatne shortcodes) do poprawnego adresu.

Tym prostym sposobem można rozbudować mechanizm linków o inne cechy i pseudo-protokoły, zależnie od potrzeb.

Na koniec warto wspomnieć o istotnej zalecie używania do cross-linków funkcji ref czy dedykowanego shortcodes. Mianowicie nazwy (identyfikatory, czy ścieżki) rozwijane są do poprawnych adresów na podstawie zbudowanych list dostępnych dokumentów. Zatem, gdy spróbujemy podlinkować się do nieistniejącej strony, zmienimy cześć dokumentu wpływającą na jego adres (tytuł, slug, data, anchor, czy co tam używamy) lub popełnimy jakiś błąd, czy literówkę, to Hugo nas o tym poinformuje odpowiednim komunikatem.

ERROR 2020/07/31 19:25:45 [pl] REF_NOT_FOUND: Ref "2006-01-01-hello-world": 
	"G:\repo\posts\2020\2020-07-31-proste-wewnetrzne-ref-linki-w-hugo\index.md:55:16": page not found

W domyślnej konfiguracji wywali po prostu błąd przerywający budowanie strony1. Jest to idealny mechanizm wykrywania niepoprawnych odnośników. Warto go stosować także w szablonie. Dzięki temu ustrzegniemy się błędnych linkowań, wynikłych nie tylko z błędów, ale i z wprowadzonych modyfikacji i braku aktualizacji wszystkich linkujących miejsc.


Przypisy

  1. Zachowanie to można zmienić w pliku konfiguracyjnym, szczegóły w dokumentacji - Ref and RelRef Configuration ↩︎

Komentarze (0)

Dodaj komentarz

/dozwolony markdown/

/nie zostanie opublikowany/