vlsiddarth's picture
Commit latest version with ranking logic and API fixes
0733aae
"""
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'<a href="{link.url}" target="_blank" '
f'style="background:#0066cc;color:white;padding:6px 12px;'
f'border-radius:4px;text-decoration:none;margin-right:8px;font-size:12px;">'
f'{link.type.upper()}</a>'
for link in source.links[:2]
])
format_badges = "".join([
f'<span style="background:#e8f0fe;color:#1a73e8;padding:2px 8px;'
f'border-radius:12px;font-size:11px;margin-right:4px;">{f.value}</span>'
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'<img src="{source.thumbnail_url}" style="width:100%;height:140px;'
f'object-fit:cover;border-radius:6px 6px 0 0;" />'
if source.thumbnail_url else ""
)
html = f"""
<div style="border:1px solid #e5e7eb;border-radius:8px;margin:8px 0;
font-family:Arial,sans-serif;overflow:hidden;max-width:480px;">
{thumbnail_html}
<div style="padding:12px;">
<div style="display:flex;justify-content:space-between;align-items:flex-start;">
<span style="font-size:11px;color:#6b7280;text-transform:uppercase;
letter-spacing:0.5px;">{icon} {source.source_platform}</span>
<span style="background:{quality_color};color:white;padding:2px 8px;
border-radius:12px;font-size:12px;font-weight:bold;">
{source.quality_score:.1f}/10
</span>
</div>
<h3 style="margin:6px 0;font-size:14px;line-height:1.4;color:#111827;">
{source.title[:80]}{'โ€ฆ' if len(source.title) > 80 else ''}
</h3>
<p style="margin:4px 0;font-size:12px;color:#374151;line-height:1.5;">
{source.summary[:200]}{'โ€ฆ' if len(source.summary) > 200 else ''}
</p>
<div style="margin:8px 0;">{format_badges}</div>
<div style="display:flex;justify-content:space-between;
font-size:11px;color:#6b7280;margin:4px 0;">
<span>Difficulty: {stars}</span>
<span>{'๐Ÿ”“ Open' if source.open_access else '๐Ÿ”’ Restricted'}</span>
</div>
{extras}
<div style="margin-top:10px;">{access_links}</div>
</div>
</div>"""
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'<div style="font-size:11px;color:#6b7280;margin:4px 0;">{items}</div>'