CreaRack-SL

Decisión: Plugin Remark custom para Mermaid en Astro (vs rehype-mermaid)

Decisión: Plugin Remark custom para Mermaid en Astro (vs rehype-mermaid)

Fecha: 2026-05-18
PR: #47
Estado: Adoptado

Contexto

El Workspace necesita renderizar diagramas ER y de flujo en las páginas wiki de base de datos (y futuras páginas técnicas). Los diagramas se escriben en bloques ```mermaid en el Markdown fuente.

Astro procesa el Markdown con Remark + Rehype y envía el HTML resultante a Shiki para colorear bloques de código. El reto es que Mermaid necesita ejecutar JavaScript en el cliente para transformar texto en SVG — no puede precalcularse en build time de forma segura.

Opciones evaluadas

Opción A — rehype-mermaid (descartada)

rehype-mermaid puede operar en modo pre-mermaid (preserva el texto raw en un <pre>) o en modo server-side (genera SVG en build). El modo server-side arrasta la dependencia mermaid-isomorphic, que a su vez requiere Playwright para simular un browser.

Problema crítico: Playwright no está disponible en el entorno de build de Cloudflare Pages. El build falla con error de binario no encontrado.

El modo pre-mermaid evita Playwright pero sigue añadiendo mermaid-isomorphic al árbol de dependencias (peso innecesario + riesgo de resolución rota en CI).

Opción B — Plugin Remark minimal custom (adoptada)

Plugin de ~30 LOC en astro.config.mjs que intercepta el AST Markdown antes de que llegue a Shiki:

function remarkMermaidPreserve() {
  return (tree) => {
    const visit = (node) => {
      if (Array.isArray(node.children)) {
        node.children = node.children.map((child) => {
          if (child.type === 'code' && child.lang === 'mermaid') {
            return {
              type: 'html',
              value: `<pre class="mermaid">${escapeHtml(child.value || '')}</pre>`,
            };
          }
          visit(child);
          return child;
        });
      }
    };
    visit(tree);
  };
}

El HTML generado contiene <pre class="mermaid"> con el código raw. En el cliente, mermaid.js (cargado bajo demanda solo si la página tiene al menos un pre.mermaid) transforma cada bloque en SVG interactivo.

Decisión

Adoptar Opción B (plugin Remark custom).

Consecuencias

Positivas

  • Zero dependencias nuevas de build: mermaid se añade a package.json solo para bundling client-side; no hay Playwright ni mermaid-isomorphic.
  • CF Pages build verde: sin binarios de sistema requeridos.
  • Carga lazy: mermaid.js (~2.5 MB minificado) solo se importa dinámicamente si la página tiene diagramas. Páginas sin diagramas no pagan el coste.
  • Theme dark: configurado en la inicialización client-side, coherente con el tema del Workspace.
  • Mantenibilidad: el plugin es autocontenido en astro.config.mjs, fácil de auditar.

Negativas / limitaciones

  • Los diagramas requieren JavaScript en el cliente para renderizarse (no hay SVG estático en el HTML servido).
  • Sin JS, el usuario ve el código fuente Mermaid en texto plano — aceptable dado que el Workspace siempre requiere JS.
  • No hay pre-rendering de SVG para OG/social cards (no es un requisito actual).

Archivos modificados

ArchivoCambio
astro.config.mjsPlugin remarkMermaidPreserve + escapeHtml + remarkPlugins: [remarkMermaidPreserve]
package.json"mermaid": "^11.15.0" añadido a dependencies
pnpm-lock.yamlLockfile actualizado

Véase también

  • [[workspace-tech—bd—tecnico]]
  • [[workspace-tech—bd—coloquial]]
  • [[crearack-tech—bd—tecnico]]
  • [[workspace—que-es-workspace]]