Jako że nie lubię redundancji kodu, chciałem stworzyć sobie konwencję do współdzielenia fragmentów kodu między wielojęzycznymi notkami (bo kod zawsze piszemy po angielsku 😉). Jak się okazuje, nie jest to takie oczywiste w Hugo.
Rozeznanie w temacie
Wydawać by się mogło, że sprawa jest banalnie prosta: tworzymy sobie jakiś katalog, odwołujemy się do umieszczonych tam plików z każdej wersji językowej i wyświetlamy w każdej to samo, a ewentualne zmiany robimy w jednym miejscu, widząc efekt w każdym. No nie bardzo 😉
Próbowałem różne podejścia, od headless bundles, przez leaf bundles, po shortcode‘y z użyciem .Site.GetPage
(podawane przez różne artykuły). Zawsze coś nie działało i podejrzewam, że ma to związek z wybraną konwencją podziału treści na katalogi.
Gdy już zacząłem rozważać zmianę konwencji i wrzucenie wszystkiego w jeden katalog (i stosowanie *.<lang>.md
dla wsparcia wielojęzyczności), w oko wpadła mi jeszcze jedna funkcja oferowana przez Hugo: readFile
. Tutaj w końcu można było odwołać się do plików spoza bieżącego contentDir
.
Implementacja skrawków
Określiłem sobie następującą strukturę plików:
hugo/
├─ content/
│ ├─ _snippets/
│ │ ├─ 2022/
│ │ │ ├─ 04/
│ │ │ │ ├─ some-post/
│ │ │ │ │ ├─ snippet1.md
│ │ │ │ │ ├─ snippet2.md
│ ├─ en/
│ │ ├─ 2022/
│ │ │ ├─ 04/
│ │ │ │ ├─ some-post.md
│ ├─ pl/
│ │ ├─ 2022/
│ │ │ ├─ 04/
│ │ │ │ ├─ jakis-post.md
Następnie stworzyłem shortcode do renderowania skrawków:
<!-- layouts/shortcodes/snippet.html -->
{{ $path := (printf "/content/_snippets/%s" (.Get 0))}}
{{ if eq (path.Ext $path) "" }}
{{ $path = (printf "%s.md" $path)}}
{{ end }}
{{ if os.FileExists (path.Clean $path) }}
{{ $page := os.ReadFile (path.Clean $path) }}
{{ $page | markdownify }}
{{ else }}
<div class="banner banner-danger">{{ i18n "invalid_snippet_reference" }}</div>
{{ end }}
Dzięki temu w postach mogę użyć:
{{</* snippet "2022/04/some-post/snippet1" */>}}
{{</* snippet "2022/04/some-post/snippet2.md" */>}}
Zaletą tego podejścia jest również fakt, że w przyszłych postach będę mógł odwoływać się do kodu użytego wcześniej poprzez zagnieżdżenie wybranego skrawka, bez konieczności powielania fragmentu kodu w kolejnym pliku. Czy są minusy? Okaże się w praktyce 😅