Menggunakan markdown render hooks pada Hugo

Setelah dua tahun migrasi Petani Kode dari Blogger ke Hugo, saya menemukan berbagai macam masalah.

Salah satu yang masih belum teratasi hingga saat ini adalah masalah pada konten. Konten-konten lama masih menggunakan HTML yang belum saya ubah menjadi markdown.

Beberapa konten memang sudah saya ubah, namun masih belum menggunakan shortcode untuk lazyload.

Konten di Petani Kode

Akibatnya, konten tersebut akan lama di-download.

Tapi kini..

Saya tidak perlu khawatir lagi. Karena sudah ada Markdown Render Hooks.

Apa itu Markdown Render Hooks?

Markdown Render Hooks adalah fitur yang ditambahkan pada Hugo versi 0.62.0 untuk membuat custom render. 1

Sejak Hugo versi 0.60, Hugo mengganti default markdown parser-nya dengna Goldmark. Mungkin karena Goldmark lebih cepat dibandingkan parser yang lain seperti Blackfriday.

Tapi, tentu ini juga akan membawa masalah baru..

Contohnya:

Ada beberapa pengguna Hugo ingin membuat link yang bisa dibuka otomatis di tab baru (target='_blank).

Pada Blackfriday, ini bisa mereka lakukan dengan mengaktifkan hrefTargetBlank.

[blackfriday]
  hrefTargetBlank = true

Sementara di Goldmark, ini belum bisa dilakukan.

Karena itu, Hugo menambahkan fitur Markdown Render Hooks untuk membuat custom render pada link dan gambar.

Oke, lalu bagaimana cara pakainya?

Cara Menggunakan Hugo Render Hooks

Sebenarnya kita cukup membuat template di dalam folder layouts/_default/_markup. Tapi sebelumnya pastikan kamu menggunakan Hugo versi 0.62 ke atas.

layouts
└── _default
    └── _markup
        ├── render-image.html
        ├── render-image.rss.xml
        └── render-link.html

Ketearangan:

  • render-image.html adalah template untuk merender image pada halaman biasa;
  • render-image.rss.xml adalah template untuk merender image pada RSS (Ini mungkin juga bisa digunakan untuk AMP dengan mengganti rss.xml menjadi amp.html);
  • render-link.html adalah template untuk me-render link.

Contoh: layouts/_defaul/_markup/render-image.html

<img 
    class='blur-up lazyload mb-3 img-fluid'
    data-sizes="auto"
    src="/img/placeholder.svg"
    data-src='{{ .Destination | safeURL }}'
    alt='{{ .Text }}'
    {{ with .Title}} title="{{ . }}"{{ end }}
    loading='lazy'
 />

Ini adalah contoh template yang saya gunakan di Petani Kode untuk me-render image agar bisa di-load dengan lazyload.

…dan pada konten markdown-nya, tinggal ditulis seperti ini:

![teks alternatif](/img/contoh-gambar.jpg "Title untuk tooltips")

Maka hasilnya akan di-render menjadi:

<img 
    class="blur-up lazyload mb-3 img-fluid"
    data-sizes="auto"
    src="/img/placeholder.svg"
    data-src="/img/contoh-gambar.jpg"
    alt="teks alternatif"
    title="Title untuk tooltips"
    loading="lazy"
 />

Dulu sebelum ada fitur ini, saya menggunakan Shortcode seperti ini:

{{< img  "/img/contoh.jpg" "Teks alt" >}}

Setiap gambar pada konten yang akan di-download dengan lazyload harus ditulis dengan shortcode.

Tapi sekarang sepertinya tidak perlu lagi.

Karena berkat Markdown Render Hooks, kita bisa membuat custom render sesuai keinginan.

Variabel di dalam Template Render Hooks

Template untuk render hooks tidak sama seperti template shortcode. Ada beberapa variabel yang bisa digunakan di dalam template render hooks:

  • Page — halaman yang di-render;
  • Destination — url dari link dan image;
  • Title — atribut title untuk link dan image;
  • Text — Teks (HTML) untuk Link dan alt teks untuk image;
  • PlainText — Teks biasa untuk link.

Contoh penggunaanya pada template render-link.html:

<a href="{{ .Destination | safeURL }}"
    {{ with .Title}} title="{{ . }}"{{ end }}
    {{ if strings.HasPrefix .Destination "http" target="_blank"{{ end }}>{{ .Text }}</a>

Artinya, jika kita membuat link yang target URL-nya memiliki http atau https maka dia akan dibuka di tab baru.

Mari kita lihat contohnya:

[Link Twitter](https://twitter.com/petanikode)

Hasilnya: Link Twitter

Selain target="_blank", kita juga bisa menambahkan atribut yang lain. Misalnya rel, bahkan juga bisa menambahkan class khusus untuk link eksternal.

Oh iya, karena variabel .Text adalah teks yang berupa HTML, maka di kita bisa menggunakan markdown untuk teksnya.

Contoh:

Jangan lupa gunakan fungsi safeHTML agar di-render menjadi HTML yang tidak ter-escape.

<a href="{{ .Destination | safeURL }}"
    {{ with .Title}} title="{{ . }}"{{ end }}
    {{ if strings.HasPrefix .Destination "http" }} target="_blank"{{ end }}
    >{{ .Text | safeHTML }}</a>

Maka saat pembuatan link, kita bisa menulis seperti ini:

- [*Link miring*](#!)
- [**Link tebal**](#!)
- [~~Link Tercoret~~](#!)
- [`Link kode`](#!)
- [<span class='badge badge-info'>Link Badge</span>](#!)

Hasilnya:

Perbedaan Shortcode dengan Render Hooks

Apakah render hooks akan menggantikan shortcode?

Tidak, shortcode akan tetap terpakai. Karena ada beberapa hal yang tidak bisa dilakukan di render hook, tapi di shortcode bisa.

Ini perbedaannya:

  • Variabel di shortcode dan render hooks berbeda;
  • Render hooks baru hanya mendukung link dan image saja;
  • Cara Kerja Render Hook dan Shotcode sama, render hooks tidak memerlukan sintaks khusus seperti shortcode;
  • Penggunaan shortcode harus menggunakan {{< ... >}} sedangkan render hooks menggunakan format markdown biasa;
  • Paramter render hooks terbatas, sedangkan shortcode bisa berapapun sesaui kebutuhan.

Jadi mau pakai render hooks atau shortcode?

Kalau dalam kasus saya.. untuk render link dan image, saya lebih memilih render hooks. Karena ada banyak konten yang masih menggunakan format markdown standar.

Tapi untuk render HTML yang kompleks, misal untuk elemen <figure>, embed tweet, embed instagram, embed video youtube, dll. Saya lebih memilih shortcode, karena hal ini belum bisa dilakukan oleh render hooks.

Akhir Kata…

Sayangnya markdown render hooks cuma baru mendukung untuk link dan image saja. Kedepan mungkin akan mendukung untuk elemen yang lain.

Kita tunggu saja Hugo versi berikutnya.

Tapi untuk saat ini, render hooks sudah menyelesaikan masalah konten di Petani Kode.


  1. https://gohugo.io/getting-started/configuration-markup/#markdown-render-hooks ↩︎