Featured image of post 'Probando mermaid.js'

'Probando mermaid.js'

¿Qué es mermaid.js?

mermaid.js es una biblioteca de JavaScript que permite describir diagramas mediante una sintaxis basada en texto (sintaxis de Mermaid) para representar gráficamente diagramas complejos como diagramas de flujo, diagramas de Gantt, etc. También se utiliza en varios servicios como GitHub, Qiita y Notion. En esta ocasión, configuraremos hugo para poder usar mermaid.js.

Habilitar mermaid.js en hugo

Los pasos son los siguientes:

  1. Añadir lo siguiente a layouts/partials/extend_footer.html:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{{ if or .Params.mermaid .Site.Params.mermaid }}
<script src="https://cdn.jsdelivr.net/npm/mermaid@10.3.0/dist/mermaid.min.js"></script>
{{- $loadmermaid := resources.Get "js/load-mermaid.js" }}
<script src="{{ $loadmermaid.RelPermalink }}"></script>
<script>
    window.initMermaid();
    if (isDarkTheme()) {
        setPrefTheme('dark');
    } else {
        setPrefTheme('light');
    }
</script>
{{ end }}
  • Solo se carga mermaid.min.js si se establece mermaid: true en la condición if. Esta biblioteca pesa aproximadamente 3MB, lo cual es sorprendentemente grande.
  1. Crear assets/js/load-mermaid.js. Este proceso se utiliza para inicializar y volver a dibujar cuando el tema cambia dinámicamente.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(function(window){
'use strict'

  const elementCode = '.mermaid'
  const loadMermaid = function(theme) {
    window.mermaid.initialize({theme})
    window.mermaid.init({theme}, document.querySelectorAll(elementCode))
  }
  const saveOriginalData = function(){
    return new Promise((resolve, reject) => {
      try {
        var els = document.querySelectorAll(elementCode),
            count = els.length;
        els.forEach(element => {
          element.setAttribute('data-original-code', element.innerHTML)
          count--
          if(count == 0){
            resolve()
          }
        });
      } catch (error) {
       reject(error) 
      }
    })
  }
  const resetProcessed = function(){
    return new Promise((resolve, reject) => {
      try {
        var els = document.querySelectorAll(elementCode),
            count = els.length;
        els.forEach(element => {
          if(element.getAttribute('data-original-code') != null){
            element.removeAttribute('data-processed')
            element.innerHTML = element.getAttribute('data-original-code')
          }
          count--
          if(count == 0){
            resolve()
          }
        });
      } catch (error) {
       reject(error) 
      }
    })
  } 

  const init = ()=>{
    saveOriginalData()
    .catch( console.error )
    document.body.addEventListener('dark-theme-set', ()=>{
      resetProcessed()
      .then(loadMermaid('dark'))
      .catch(console.error)
    })
    document.body.addEventListener('light-theme-set', ()=>{
      resetProcessed()
      .then(loadMermaid('default'))
      .catch(console.error)
    })
  }
  window.initMermaid = init
})(window);

El código original en el que me basé fue tomado de la siguiente referencia:

  1. Modificar el procesamiento al cambiar de tema en header.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function switchTheme(theme) {
  switch (theme) {
    case 'light':
{{ if or .Params.mermaid .Site.Params.mermaid }}
      document.body.dispatchEvent(new CustomEvent('light-theme-set'));
{{ end }}
      document.body.classList.remove('dark');
      break;
    case 'dark':
{{ if or .Params.mermaid .Site.Params.mermaid }}
      document.body.dispatchEvent(new CustomEvent('dark-theme-set'));
{{ end }}
      document.body.classList.add('dark');
      break;
    // auto
    default:
      if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
{{ if or .Params.mermaid .Site.Params.mermaid }}
        document.body.dispatchEvent(new CustomEvent('dark-theme-set'));
{{ end }}
        document.body.classList.add('dark');
      }
  }
}
  1. Crear layouts/shortcodes/mermaid.html
1
2
3
<div class="mermaid" align="{{ if .Get "align" }}{{ .Get "align" }}{{ else }}center{{ end }}">
  {{ safeHTML .Inner }}
</div>

Con esto, la preparación para usar mermaid.js está completa.

Probando mermaid.js

  1. Añadir lo siguiente a la definición del artículo:
1
marmaid: true
  1. Añadir lo siguiente al cuerpo del artículo:

Diagrama de flujo

1
2
3
4
5
6
{{<mermaid align="center">}}
graph TD
    A[Inicio] -->|Condición 1| B(Condición 2)
    B --> C{Condición 3}
    C -->|Condición 4| D[Fin]
{{</mermaid>}}

Resultado de salida

graph TD A[Inicio] -->|Condición 1| B(Condición 2) B --> C{Condición 3} C -->|Condición 4| D[Fin]

Diagrama de Gantt

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{{<mermaid align="center">}}
gantt
    section Project
    Definición de requisitos :done,      a, 2024-05-25, 5d
    Diseño básico :done,      b, after a,    5d
    Diseño detallado :done,      c, after b,    5d
    Implementación    :active,    d, after c,    10d
    Pruebas unitarias :crit,      e, after d,    5d
    Pruebas de integración :           f, after e,    5d
    Pruebas del sistema :           g, after f,    5d
    Lanzamiento :milestone, h, after g,    1d
{{</mermaid>}}

Resultado de salida

gantt section Project Definición de requisitos :done, a, 2024-05-25, 5d Diseño básico :done, b, after a, 5d Diseño detallado :done, c, after b, 5d Implementación :active, d, after c, 10d Pruebas unitarias :crit, e, after d, 5d Pruebas de integración : f, after e, 5d Pruebas del sistema : g, after f, 5d Lanzamiento :milestone, h, after g, 1d

Diagrama de secuencia

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{{<mermaid align="center">}}
sequenceDiagram
    participant user
    participant view
    participant controller
    participant model
    participant database
    user->>view: Ingreso de ID/PW
    view->>controller: Petición de autenticación
    controller->>model: Petición de autenticación
    model->>database: Petición de autenticación
    database-->>model: Devolución de resultado de autenticación
    model-->>controller: Devolución de resultado de autenticación
    controller-->>view: Devolución de resultado de autenticación
    view-->>user: Mostrar resultado de autenticación
{{</mermaid>}}

Resultado de salida

sequenceDiagram participant user participant view participant controller participant model participant database user->>view: Ingreso de ID/PW view->>controller: Consulta ajax controller->>model: Petición de autenticación model->>database: Emisión de SQL database-->>model: Devolución de resultado SQL model-->>controller: Devolución de resultado de petición de autenticación controller-->>view: Devolución de resultado de consulta ajax view-->>user: Mostrar resultado de autenticación

Eso es todo.

Referencias

comments powered by Disqus