Volver a la wiki

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

Negativas / limitaciones

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

Subir