from __future__ import annotations
import html
import json
from typing import Any
def _icon_for_source(source_type: str) -> str:
st = (source_type or "").lower()
if st in ("web", "url", "scrape"):
return "language"
if st == "pdf":
return "picture_as_pdf"
return "description"
def render_doc_cards(documents: list[dict[str, Any]], *, rag_active: bool) -> str:
if not documents:
return (
'
No documents indexed yet. Paste a URL or upload a file.
'
)
badge = (
'RAG Active'
if rag_active
else 'No sources'
)
cards: list[str] = []
for doc in documents:
title = html.escape(str(doc.get("title") or "Untitled"))
meta = html.escape(str(doc.get("meta") or ""))
icon = _icon_for_source(str(doc.get("source_type") or ""))
cards.append(
f"""
{icon}
{title}
{meta}
"""
)
return f'
{badge}
{"".join(cards)}
'
def render_slide_canvas(preview_html: str, *, empty_message: str | None = None) -> str:
if not preview_html or not preview_html.strip():
msg = html.escape(empty_message or "Generate slides to preview your lesson here.")
return f'
{msg}
'
return f'
{preview_html}
'
def render_gallery_strip(image_paths: list[str]) -> str:
if not image_paths:
return ""
items: list[str] = []
for index, path in enumerate(image_paths):
if not path:
continue
src = html.escape(f"/file={path}")
alt = html.escape(f"Slide {index + 1}")
items.append(
f''
f''
)
if not items:
return ""
return f'
Speak your lesson, then analyze for pace and filler feedback.
"""
if pace_score is None and not tip and not report_md and not transcript_html:
return """
Record a pitch below, then click Analyze pitch for metrics.
"""
score = pace_score if pace_score is not None else "—"
pace = f"{wpm:.0f}" if wpm is not None else "—"
tip_html = html.escape(tip or "")
report_block = ""
if report_md:
safe = html.escape(report_md[:1200])
report_block = f'
{safe}
'
transcript_block = ""
if transcript_html:
transcript_block = f'
{transcript_html}
'
charts: list[str] = []
filler_url = _file_url(filler_chart)
pace_url = _file_url(pace_chart)
if filler_url:
charts.append(
f'Filler words'
f''
)
if pace_url:
charts.append(
f'Pace timeline'
f''
)
charts_block = ""
if charts:
charts_block = f'
{"".join(charts)}
'
voiceout_block = ""
voiceout_url = _file_url(voiceout_path)
if voiceout_url:
voiceout_block = (
f'
'
f'
VoiceOut feedback
'
f'
'
)
return f"""
Analysis resultsEchoCoach
Pace score
{score}
Pace (WPM)
{pace}
{f'
{tip_html}
' if tip_html else ''}
{transcript_block}
{charts_block}
{voiceout_block}
{report_block}