Spaces:
Running
Running
File size: 4,874 Bytes
0733aae | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | """
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>' |