ddebree's picture
Upload folder using huggingface_hub
f9306c2 verified
"""HTML export for visual inspection of MathVision-like records."""
from __future__ import annotations
from html import escape
from pathlib import Path
from mathvision_explorer.dataset import MathVisionRecord
def export_html(records: list[MathVisionRecord], output: Path) -> None:
"""Write a standalone HTML gallery for records."""
output.parent.mkdir(parents=True, exist_ok=True)
cards = "\n".join(_render_card(record, output_dir=output.parent) for record in records)
html = f"""<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>MathVision Explorer</title>
<style>
body {{
margin: 0;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: #172033;
background: #f7f8fb;
}}
header {{
padding: 28px 32px 18px;
background: #ffffff;
border-bottom: 1px solid #dde3ee;
}}
h1 {{
margin: 0 0 6px;
font-size: 28px;
font-weight: 750;
}}
main {{
display: grid;
gap: 18px;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
padding: 24px 32px 36px;
}}
article {{
overflow: hidden;
border: 1px solid #d8deea;
border-radius: 8px;
background: #ffffff;
}}
img {{
display: block;
width: 100%;
aspect-ratio: 3 / 2;
object-fit: contain;
background: #eef2f7;
}}
.body {{
padding: 16px;
}}
.meta {{
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 12px;
font-size: 13px;
}}
.tag {{
padding: 3px 8px;
border: 1px solid #cfd7e6;
border-radius: 999px;
background: #f4f7fb;
}}
h2 {{
margin: 0 0 12px;
font-size: 16px;
line-height: 1.35;
}}
p {{
margin: 8px 0 0;
line-height: 1.45;
}}
.answer {{
font-weight: 700;
}}
</style>
</head>
<body>
<header>
<h1>MathVision Explorer</h1>
<div>{len(records)} visual math records</div>
</header>
<main>
{cards}
</main>
</body>
</html>
"""
output.write_text(html, encoding="utf-8")
def _render_card(record: MathVisionRecord, *, output_dir: Path) -> str:
image_html = ""
if record.image_path is not None:
image_src = _relative_or_absolute_image(record.image_path, output_dir=output_dir)
image_html = f' <img src="{escape(image_src)}" alt="{escape(record.problem_id)}">\n'
meta = [_tag(record.problem_id)]
if record.subject is not None:
meta.append(_tag(record.subject))
if record.level is not None:
meta.append(_tag(f"level {record.level}"))
options = ""
if record.options:
options = f"<p>Options: {escape(', '.join(record.options))}</p>"
solution = ""
if record.solution:
solution = f"<p>{escape(record.solution)}</p>"
return f""" <article>
{image_html} <div class="body">
<div class="meta">{''.join(meta)}</div>
<h2>{escape(record.question)}</h2>
<p class="answer">Answer: {escape(record.answer)}</p>
{options}
{solution}
</div>
</article>"""
def _tag(value: str) -> str:
return f'<span class="tag">{escape(value)}</span>'
def _relative_or_absolute_image(image_path: Path, *, output_dir: Path) -> str:
try:
return image_path.resolve().relative_to(output_dir.resolve()).as_posix()
except ValueError:
return image_path.resolve().as_uri()