"""Renderiza un grafo sigma.js como HTML standalone con dark theme y layout ForceAtlas2."""
import json
import os
_HTML_TEMPLATE = """\
{title}
"""
def render_sigma_html(
graph_data: dict,
output_path: str,
title: str = "OSINT Graph",
) -> str:
"""Genera un HTML standalone con sigma.js que visualiza el grafo OSINT.
Recibe el dict producido por ops_to_sigma_json, embebe los datos como JSON
en el HTML, aplica ForceAtlas2 (500 iteraciones sincrono) y renderiza con
sigma.js v2.4. Incluye dark theme, panel de filtros por tipo de nodo y
tooltip con metadata al hacer hover.
Args:
graph_data: Dict con claves 'nodes' y 'edges' en formato graphology/sigma.
output_path: Ruta del archivo HTML a escribir.
title: Titulo del grafo mostrado en el panel y la pestana.
Returns:
Ruta absoluta del archivo HTML escrito.
Raises:
Exception: Si no se puede escribir el archivo en output_path.
"""
json_data = json.dumps(graph_data, ensure_ascii=False)
html = _HTML_TEMPLATE.format(
title=title,
json_data=json_data,
)
abs_path = os.path.abspath(output_path)
os.makedirs(os.path.dirname(abs_path) or ".", exist_ok=True)
try:
with open(abs_path, "w", encoding="utf-8") as f:
f.write(html)
except OSError as exc:
raise Exception(f"render_sigma_html: no se pudo escribir '{abs_path}': {exc}") from exc
return abs_path