Files
Auto-Trader/agent/src/research_card/render_html.py
T
2026-07-06 17:02:44 +08:00

47 lines
1.6 KiB
Python

"""Escaped HTML renderer for Research Cards."""
from __future__ import annotations
from html import escape
from src.research_card.model import ResearchCard
def render_research_card_html(card: ResearchCard) -> str:
"""Render escaped, self-contained HTML without accepting raw HTML."""
parts = [
"<!doctype html>",
'<html lang="en">',
"<head>",
'<meta charset="utf-8">',
f"<title>{escape(card.title)}</title>",
"</head>",
"<body>",
f"<h1>Research Card: {escape(card.title)}</h1>",
"<dl>",
f"<dt>Card ID</dt><dd><code>{escape(card.card_id)}</code></dd>",
f"<dt>Schema Version</dt><dd><code>{escape(card.schema_version)}</code></dd>",
f"<dt>Conclusion</dt><dd><code>{escape(card.conclusion_level)}</code></dd>",
"</dl>",
"<h2>Hypothesis</h2>",
f"<p>{escape(card.hypothesis or 'Not recorded.')}</p>",
]
if card.warnings:
parts.extend(["<h2>Warnings</h2>", "<ul>"])
for warning in card.warnings:
parts.append(
f"<li><code>{escape(warning.code)}</code> "
f"({escape(warning.severity)}): {escape(warning.message)}</li>"
)
parts.append("</ul>")
if card.hard_failures:
parts.extend(["<h2>Hard Failures</h2>", "<ul>"])
for failure in card.hard_failures:
parts.append(
f"<li><code>{escape(failure.code)}</code> "
f"({escape(failure.severity)}): {escape(failure.message)}</li>"
)
parts.append("</ul>")
parts.extend(["</body>", "</html>"])
return "\n".join(parts) + "\n"