prehistoric.me

Membuat Diagram dengan Kroki, Vim, dan Browser

Kadang saya perlu membuat diagram seperti flowchart atau sequence diagram. Dalam membuatnya saya terbiasa menggunakan sintaks PlantUML. Ada beberapa perangkat yang bisa dipakai untuk menulis kode diagram dan melihat tampilan digramnya secara instan, misal dengan menggunakan website plantuml.com atau dengan fasitilitas edit code dari draw.io. Semua perangkat tersebut memiliki kelemahan yang sama, yaitu editornya bukan vi(m). Singkatnya, yang diinginkan adalah cara untuk mengetik sintaks diagram dari editor vim (atau editor apapun yang punya keymap seperti vim), dan bisa melihat hasilnya secara (hampir) realtime.

Setelah bereksperimen beberapa kali, saya pun membuat workflow yang sampai sekarang paling mudah dan praktis untuk menulis diagram. Proses konversi menjadi gambar diagram dilakukan dengan kroki. Kroki dipilih karena mendukung berbagai macam sintaks dan jenis diagram, dan tersedia dalam bentuk file jar yang bisa dijalankan langsung dengan java. Kemudian saya membuat file template HTML yang berisi tempat kita menuliskan sintaks diagram dan perintah JS untuk mengonversi sintaks tersebut menjadi gambar diagram melalui HTTP call ke kroki. Isi file template tersebut seperti ini.

<html>
  <script type="text/plain" id="source">
@startuml
actor Saya as s
participant Disk as d
participant Browser as b
participant Kroki.jar as k

s -> k: Jalankan ""kroki.jar"" di shell
s -> s: Buka file //diagram.html// di editor
s -> s: Ketik sintaks diagram di editor
s -> d: Save file
s -> b: Buka file //diagram.html// di browser
loop refresh setiap 5 detik
  b -> d: Muat isi file terkini
  d --> b: Isi file terkini
  b -> k: Kirimkan sintaks diagram
  k --> b: Respon dengan gambar diagram
  b -> s: Tampilkan gambar diagram
end
@enduml
</script>

  <body>
    <form autocomplete="on">
      <fieldset>
        <legend>Configs</legend>
        <input type="checkbox" name="autoreload" id="cbAutoReload" checked/><label for="cbAutoReload">Autoreload</label>
        <input type="radio" name="format" value="png" id="rdPng"/><label for="rdPng">png</label>
        <input type="radio" name="format" value="svg" id="rdSvg" checked/><label for="rdSvg">svg</label>
      </fieldset>
    </form>
    <div id="result"></div>
    <script>
      const resultContainer = document.getElementById('result');
      const cbAutoReload = document.getElementById('cbAutoReload');
      const rdSvg = document.getElementById('rdSvg');

      function png() {
        const source = document.querySelector('#source').innerHTML;

        fetch('http://localhost:8000/plantuml/png', { method: 'POST', body: source })
          .then(response => response.blob())
          .then(imageBlob => {
            const imageUrl = URL.createObjectURL(imageBlob);
            resultContainer.innerHTML = `<img src="${imageUrl}" />`;
          });
      }

      function svg() {
        const source = document.querySelector('#source').innerHTML;

        fetch('http://localhost:8000/plantuml/svg', { method: 'POST', body: source })
          .then(response => response.text())
          .then(bodyText => { resultContainer.innerHTML = bodyText; });
      }


      function storeFormat() {
          if (rdSvg.checked) {
            localStorage.setItem('isSvg', 'true');
          } else {
            localStorage.setItem('isSvg', 'false');
          }
      }

      function loadFormat() {
        const formatIsSvg = localStorage.getItem('isSvg');

        if (formatIsSvg === 'true') {
          rdSvg.checked = true;
        } else {
          rdPng.checked = true;
        }
      }

      function loadImage() {
        loadFormat();

        if (rdSvg.checked) {
          svg();
        } else {
          png();
        }
      }

      loadImage();
      setInterval(() => {
        if (cbAutoReload.checked) {
          storeFormat();
          window.location.reload();
        }
      }, 5000);
    </script>
  </body>
</html>

Bisa dilihat kode diagram ditulis di antara block <script type="text/plain" id="source"></script>. Isi block script tersebut itu dikirimkan ke server lokal kroki dengan method fetch() via HTTP. Ada checkbox dan radio button untuk mengatur format yang diinginkan dan apakah tampilan perlu diperbarui secara berkala.

Berkas template tersebut disimpan di folder $HOME/Templates. Setiap kali akan membuat diagram baru, saya menggunakan menu "Create Document > diagram" di program file manager (thunar), atau dengan cp jika melakukannya via terminal. Gambaran prosesnya kira-kira seperti ini:

Sequence Diagram cara kerja dibuatnya diagram ini.

Pembaruan tampilan dilakukan secara berkala tiap 5 detik dengan melakukan reload halaman secara penuh. Ini dilakukan supaya perubahan terkini pada isi block script bisa dimuat ulang untuk kemudian dikirimkan ke server kroki. Jika ingin mengubah format sintaks yang digunakan dan jenis diagram yang dihasilkan, bisa dilakukan dengan mengubah path yang dipanggil oleh method fetch(). Daftar lengkapnya bisa dicek di halaman web kroki.


Halaman depan / Semua Tulisan / Perihal / Blogroll