""" Knowledge Universe — HTML Format Adapter Rich HTML cards for UI rendering. Each format gets its own card layout: video → thumbnail + play button jupyter → code preview + Colab link dataset → stats + download button podcast → artwork + episode count pdf → page count + download button github → stars + clone button """ from typing import Any from src.api.models import Source, SourceFormat from src.format_adapters.base_adapter import BaseFormatAdapter class HTMLFormatAdapter(BaseFormatAdapter): """ Produces rich HTML cards per source type. Used by the Streamlit demo and any HTML-consuming client. """ FORMAT_ICONS = { "pdf": "📄", "video": "▶️", "jupyter": "📓", "github": "🐙", "dataset": "📊", "podcast": "🎧", "audio": "🔊", "html": "🌐", "epub": "📚", "markdown": "📝", "sandbox": "🎮", "simulation": "🔬", "knowledge_graph": "🕸️", "problem_set":"📐", "flashcards": "🃏", "3d_model": "🧊", "map": "🗺️", "timeseries": "📈", "stackoverflow": "💬", "colab": "⚡", } def transform(self, source: Source) -> str: fmt = source.formats[0].value if source.formats else "html" icon = self.FORMAT_ICONS.get(fmt, "🔗") stars = "⭐" * source.difficulty access_links = "".join([ f'' f'{link.type.upper()}' for link in source.links[:2] ]) format_badges = "".join([ f'{f.value}' for f in source.formats[:4] ]) # Platform-specific extras extras = self._platform_extras(source) quality_color = ( "#22c55e" if source.quality_score >= 7.5 else "#f59e0b" if source.quality_score >= 5.0 else "#ef4444" ) thumbnail_html = ( f'' if source.thumbnail_url else "" ) html = f"""
{thumbnail_html}
{icon} {source.source_platform} {source.quality_score:.1f}/10

{source.title[:80]}{'…' if len(source.title) > 80 else ''}

{source.summary[:200]}{'…' if len(source.summary) > 200 else ''}

{format_badges}
Difficulty: {stars} {'🔓 Open' if source.open_access else '🔒 Restricted'}
{extras}
{access_links}
""" return html def _platform_extras(self, source: Source) -> str: """Platform-specific metadata rows.""" extras = [] if source.stars is not None: extras.append(f"⭐ {source.stars:,} stars") if source.views is not None: extras.append(f"👁 {source.views:,} views") if source.downloads is not None: extras.append(f"⬇ {source.downloads:,} downloads") if source.duration_seconds: mins = source.duration_seconds // 60 extras.append(f"⏱ {mins} min") if source.page_count: extras.append(f"📃 {source.page_count} pages") if source.citation_count: extras.append(f"📚 {source.citation_count} citations") if not extras: return "" items = " · ".join(extras) return f'
{items}
'