BanditHijo.dev

Membuat Jekyll Custom Tags dengan Liquid Tags

Created at: 2021-01-22
Author by: BanditHijo

Latar Belakang Masalah

Seiring berjalannya waktu, jumlah post di BanditHijo Blog ini semakin banyak.

Saya pun sudah beberapa kali merubah beberapa style untuk beberapa komponen terutama komponen seperti tampilan terminal prompt atau code block. Masih mencari-cari style seperti apa yang pas dan mudah untuk dipahami.

Ketika style baru ditemukan, maka style yang lama juga mau tidak mau harus ikut diubah.

Sangat ribet sekali bukan?

Belum lagi, bentuk dari stylenya adalah HTML yang bercampur dengan Markdown di dalam post.

Misal seperti ini,

_posts/blog/2021/2021-01-01-contoh-artikel.md
1Lorem ipsum dolor sit amet consectetur adipisicing elit. Totam neque quod, debitis maxime nostrum quibusdam.
2Harum ullam repudiandae beatae nesciunt ea ipsam nisi? Quasi quae aliquid ratione vel blanditiis vitae.
3
4<pre>
5$ <b>sudo pacman -Syu</b>
6$ <b>sudo pacman -S ruby</b>
7</pre>
8
9Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla doloribus, labore dicta dolore magnam maiores.
10Inventore expedita minus accusantium deserunt ipsum pariatur magni, cum reiciendis maxime.
11Aperiam incidunt tempora natus?
12
13<!-- INFORMATION -->
14<div class="blockquote-blue">
15<div class="blockquote-blue-title"><img src="/assets/img/logo/logo_note.svg">Informasi</div>
16<p markdown=1>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ex sapiente dicta,<br>
17consequuntur veritatis, ipsum quos, hic dolores alias possimus reiciendis doloremque cupiditate nisi.<br>
18Quaerat adipisci blanditiis sit quos, soluta iste.<p>
19</div>

Baris ke 4-7, adalah prompt terminal.

Baris ke 13-19, adalah contoh dari quote informasi yang berwarna biru.

Nah, yang menjadi masalah adalah, bayangkan apabila terdapat ratusan artikel dan kita ingin merubah stylenya.

Mungkin gak? Masih mungkin, tapi cukup bikin mumet kepala. 😅

Apa yang saya inginkan?

Saya ingin menggunakan sesuatu semacam wadah, yang apabila ingin merubah stylenya, kita cukup merubah si wadah saja, dan semua yang menggunakan wadah tersebut otomatis ikut berubah juga.

Dan wadah tersebut harus sederhana. Cukup sederhana untuk ditulis dan dibaca.

Seperti ini,

_posts/blog/2021/2021-01-01-contoh-artikel.md
1Lorem ipsum dolor sit amet consectetur adipisicing elit. Totam neque quod, debitis maxime nostrum quibusdam.
2Harum ullam repudiandae beatae nesciunt ea ipsam nisi? Quasi quae aliquid ratione vel blanditiis vitae.
3
4{% shell_user %}
5sudo pacman -Syu
6sudo pacman -S ruby
7{% endshell_user %}
8
9Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla doloribus, labore dicta dolore magnam maiores.
10Inventore expedita minus accusantium deserunt ipsum pariatur magni, cum reiciendis maxime.
11Aperiam incidunt tempora natus?
12
13{% box_info %}
14<p markdown=1>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ex sapiente dicta,<br>
15consequuntur veritatis, ipsum quos, hic dolores alias possimus reiciendis doloremque cupiditate nisi.<br>
16Quaerat adipisci blanditiis sit quos, soluta iste.<p>
17{% endbox_info %}

Pada contoh di atas, saya menggunakan module Liquid::Block untuk membungkus konten yang ingin saya tampilkan.

1{% nama_tag %}
2# konten
3# yang ingin ditampilkan
4# bisa dalam bentuk multiline
5{% endnama_tag %}

Fitur ini, disebut dengan Liquid Tags. Fitur ini disediakan oleh Jekyll karena Jekyll menggunakan Liquid sebagai bahasa template.

Oke, karena keterbatasan ilmu saya saat ini, yang ingin saya catat hanya hal yang dasar saja dalam membuat Liquid tags yang juga digunakan di blog ini.

Mungkin artikel ini akan berkesinambungan seiring bertambahnya teknik yang saya dapatkan.

Praktik Membuat Liquid Tags

Di Jekyll, saya melihat pada module Tags menggunakan setidaknya Liquid::Block dan juga Liquid::Tags.

Liquid tags yang disediakan oleh Jekyll, pasti teman-teman pernah menggunakannya.

  1. highlight, menggunakan Liquid::Block (lib/jekyll/tags/highlight.rb)
  2. include, menggunakan Liquid::Tags (lib/jekyll/tags/include.rb)
  3. link, menggunakan Liquid::Tags (lib/jekyll/tags/link.rb)

Nah, kita akan mamanfaatkan kedua module ini untuk membuat Liquid tags yang kita perlukan.

Misal, kalau di BanditHijo, saya lebih banyak memerlukan untuk menampilkan command prompt, highlight code, dan image.

Pertama-tama, karena kita menggunakan Jekyll, kita akan menganggap fitur yang kita buat ini sebagai plugin.

Maka kita akan menempatkannya pada direktori _plugins/.

.
├── 📂 _plugins/
│   ├── 📄 images.rb
│   └── 📄 shells.rb
...

Dapat dilihat, kalau saya memiliki beberapa custom plugin yang saya buat untuk memudahkan proses menulis di blog ini.

Ayo kita lihat!

Liquid::Tags dengan Parameter

Rasanya, penggunaan module Liquid::Tags memang hampir semuanya menggunakan parameter.

Image Tag

Saya menggunakannya untuk menghandle image.

Sebelum mengenal Liquid tags, saya menggunakan cara ini untuk memasukkan gambar.

_posts/blog/2021/2021-01-01-contoh-artikel.md
1![gambar_1]({{ site.lazyload.logo_blank }}){:data-echo="https://i.postimg.cc/wT7rfFFX/gambar-01.png" onerror="imgError(this);"}{:class="myImg"}

Ribet banget yaa.

Saya membuat snippets agar tidak ribet saat akan menggunakannya, namun, tetap saja hal ini membuat markdown file yang kita tulis menjadi kotor.

Saya ingin terlihat lebih rapi tanpa terlalu banyak HTML tag.

Kira-kira seperti ini,

_posts/blog/2021/2021-01-01-contoh-artikel.md
1{% image https://i.postimg.cc/wT7rfFFX/gambar-01.png" | 1 | Ini adalah caption }
2

Nah! Lebih sederhana kan?

Berikut ini adalah codenya,

_plugins/shells.rb
1module Jekyll
2 class Image < Liquid::Tag
3 def initialize(tag_name, input, tokens)
4 super
5 @input = input
6 end
7
8 def render(context)
9 params = split_params(@input)
10 url = params[0].strip
11 num = params[1].strip if params.length > 1
12 cap = params[2].strip if params.length > 2
13
14 output = "![gambar_#{num}](/assets/img/logo/logo_blank.svg){:data-echo='#{url}' onerror='imgError(this);'}{:class='myImg'}"
15 output += "\n<p class='img-caption' markdown='1'>Gambar #{num} - #{cap}</p>" if params.length == 3
16 output
17 end
18
19 def split_params(params)
20 params.split(' | ')
21 end
22 end
23end
24
25Liquid::Template.register_tag('image', Jekyll::Image)

Blok kode di atas adalah untuk kebutuhan saya.

Tentunya, teman-teman perlu memodifikasi sesuai dengan yang teman-teman butuhkan.

Liquid::Block Tanpa Parameter

Untuk membuat Liquid::Block Tanpa Parameter, cukup mudah.

Command Prompt

Saya akan contohkan untuk shells.rb, yang saya gunakan untuk menyimpan beberapa prompt shell untuk user dan root.

Kalau teman-teman lihat tampilan prompt seperti di bawah ini:

$ sudo pacman -Syy
# systemctl start NetworkManager.service

Kedua tampilan prompt di atas, digenerate dari Liquid tags yang berasal dari file plugin shells.rb tersebut.

Pada tampilan markdownya akan seperti ini:

_posts/blog/2021/2021-01-01-contoh-artikel.md
1{% shell_user %}
2sudo pacman -Syy
3{% endshell_user %}
_posts/blog/2021/2021-01-01-contoh-artikel.md
1{% shell_root %}
2systemctl start NetworkManager.service
3{% endshell_root %}

Nah! Sekarang saya akan perlihatkan isi dari plugin shells.rb.

_plugins/shells.rb
1module Jekyll
2 class ShellRoot < Liquid::Block
3 def render(context)
4 commands = super.split("\n")
5 text = '<pre>'
6 text += commands[1..].map do |i|
7 "<span class='cmd'># </span><b>#{i}</b><br>"
8 end.join.to_s
9 text += '</pre>'
10 text
11 end
12 end
13
14 class ShellUser < Liquid::Block
15 def render(context)
16 commands = super.split("\n")
17 text = '<pre>'
18 text += commands[1..].map do |i|
19 "<span class='cmd'>$ </span><b>#{i}</b><br>"
20 end.join.to_s
21 text += '</pre>'
22 text
23 end
24 end
25end
26
27Liquid::Template.register_tag('shell_root', Jekyll::ShellRoot)
28Liquid::Template.register_tag('shell_user', Jekyll::ShellUser)

Dapat dilihat bahwa saya membangun sebuah prompt dengan menggunakan pre tag.

<pre>
<span class="cmd">$ </span><b>command terminal</b>
</pre>

Style dari prompt ini adalah:

assets/css/main.css
1/* Untuk box dari command */
2pre {
3 background: #002b36;
4 border-radius: 5px;
5 font-size: 14px;
6 font-family: 'FiraCodeNerdFontComplete-Medium','Roboto Mono', monospace;
7 line-height: 1.45;
8 overflow: auto;
9 padding: 10px;
10}
11
12/* Untuk mewarnai command terminal menjadi kuning */
13pre b {
14 color: #FFCC00;
15}
16
17/* Untuk mendisable selection dari simbol prompt */
18pre span.cmd {
19 user-select: none;
20 -webkit-user-select: none;
21 -ms-user-select: none;
22 -webkit-touch-callout: none;
23 -o-user-select: none;
24 -moz-user-select: none;
25}

Fitur dari Liquid tags ini adalah,

  1. Setiap baris baru (newline), akan diconvert menjadi 1 baris command (perintah).

Seperti ini contohnya:

_posts/blog/2021/2021-01-01-contoh-artikel.md
1{% shell_user %}
2mkdir project
3cd project
4git clone https://github.com/bandithijo/new_project
5cd new_project
6bundle exec jekyll server
7{% endshell_user %}

Hasilnya:

$ mkdir project
$ cd project
$ git clone https://github.com/bandithijo/new_project
$ cd new_project
$ bundle exec jekyll server

Nah, sederhana kan?

Liquid::Block dengan Parameter

Untuk membuat Liquid::Block dengan Parameter, cukup tricky tapi mungkin.

Command Prompt

Saya akan contohkan lagi untuk Command Prompt tapi dapat kita definisikan sendiri bentuk dari prompt dan warnanya.

Seperti ini misalnya,

_posts/blog/2021/2021-01-01-contoh-artikel.md
1{% shell_term $ %}
2sudo pacman -Syu
3sudo pacman -Scc
4{% endshell_term %}
$ sudo pacman -Syu
$ sudo pacman -Scc

Atau,

_posts/blog/2021/2021-01-01-contoh-artikel.md
1{% shell_term # %}
2pacman -Syu
3pacman -Scc
4{% endshell_term %}
# pacman -Syu
# pacman -Scc

Saya menggunakan parameter $ untuk mengindikasikan user biasa dan # untuk mengindikasikan root.

Atau, dengan parameter warna

_posts/blog/2021/2021-01-01-contoh-artikel.md
1{% shell_term [arch@iso ~]# | #DC322F %}
2mkdir project
3cd project
4git clone https://github.com/bandithijo/new_project
5cd new_project
6bundle exec jekyll server
7{% endshell_term %}
[arch@iso ~]# mkdir project
[arch@iso ~]# cd project
[arch@iso ~]# git clone https://github.com/bandithijo/new_project
[arch@iso ~]# cd new_project
[arch@iso ~]# bundle exec jekyll server

Jadi lebih fleksible.

Nah! Codenya seperti ini.

_plugins/shells.rb
1module Jekyll
2 class ShellCommand < Liquid::Block
3 def initialize(tag_name, input, tokens)
4 super
5 @input = input
6 end
7
8 def render(context)
9 params = split_params(@input)
10 prompt_symbol = params[0]&.strip
11 prompt_color = params[1]&.strip if params.length > 1
12
13 commands = super.split("\n")
14 output = '<pre>'
15 output += commands[1..].map do |i|
16 "<span class='cmd' #{"style='color:#{prompt_color};'" unless prompt_color.nil?}>" \
17 "#{prompt_symbol.nil? ? '$' : prompt_symbol} </span><b>#{i}</b><br>"
18 end.join.to_s
19 output += '</pre>'
20 output
21 end
22
23 def split_params(params)
24 params.split(' | ')
25 end
26 end
27end
28
29Liquid::Template.register_tag('shell_term', Jekyll::ShellCommand)

Pesan Penulis

Sepertinya, segini dulu yang dapat saya tuliskan.

Mudah-mudahan dapat bermanfaat.

Terima kasih.

(^_^)

Referensi

  1. jekyllrb.com/docs/liquid/tags/
    Diakses tanggal: 2021/01/22

  2. jekyllrb.com/docs/plugins/your-first-plugin/
    Diakses tanggal: 2021/01/22

  3. blog.sverrirs.com/2016/04/custom-jekyll-tags.html
    Diakses tanggal: 2021/01/25