ankira / diff_html.py
nofater's picture
Upload folder using huggingface_hub
12bf126 verified
Raw
History Blame Contribute Delete
2.45 kB
"""Render a GradeReport as color-coded HTML for the Gradio Space.
This is the presentation layer over the deterministic grader in
space.ocr.grading (spec §7): the diff and score are computed there; here we
only turn the report into spans the learner can read. Pure, no network.
"""
import html
try: # package context (space.diff_html, e.g. tests at repo root)
from .ocr.grading import GradeReport
except ImportError: # flat context (HF Space root, app.py)
from ocr.grading import GradeReport
# Inline styles (Gradio sanitizes <style> blocks; inline survives).
_CORRECT = "color:#16794a;"
_WRONG = "color:#c0392b;font-weight:600;"
_MISSING = "color:#b9770e;font-style:italic;"
_EXTRA = "color:#8e44ad;font-style:italic;text-decoration:line-through;"
def _verdict(accuracy: float) -> str:
if accuracy >= 0.95:
return "Excellent"
if accuracy >= 0.8:
return "Good"
if accuracy >= 0.6:
return "Keep practicing"
return "Needs work"
def render_report_html(report: GradeReport) -> str:
"""Color-coded word-level diff plus a score header (spec §7)."""
s = report.summary
score = round(s.accuracy * 100)
spans: list[str] = []
for w in report.words:
if w.status == "correct":
spans.append(f'<span style="{_CORRECT}">{html.escape(w.read or "")}</span>')
elif w.status == "misspelled":
wrote = html.escape(w.read or "")
correct = html.escape(w.expected or "")
spans.append(
f'<span style="{_WRONG}" title="{html.escape(w.diff or "")}">'
f"{wrote}{correct}</span>"
)
elif w.status == "missing":
spans.append(
f'<span style="{_MISSING}">[missing: {html.escape(w.expected or "")}]</span>'
)
else: # extra
spans.append(
f'<span style="{_EXTRA}">[extra: {html.escape(w.read or "")}]</span>'
)
body = " ".join(spans) if spans else "<em>No text recognized.</em>"
return (
f'<div style="font-size:1.05rem;line-height:1.7;">'
f'<p style="font-size:1.2rem;margin:0 0 .4rem;">'
f"<strong>{score}%</strong> &middot; {_verdict(s.accuracy)} "
f'<span style="color:#666;">({s.correct}/{s.total} correct, '
f"misspelled {s.misspelled}, missing {s.missing}, extra {s.extra})</span></p>"
f"<p>{body}</p>"
f"</div>"
)