"""Render uploaded assets for Markdown documents."""
from __future__ import annotations
import json
from html import escape
from urllib.parse import quote, urlsplit
from pathlib import Path
from .uploader import UploadedAsset
def default_label(asset: UploadedAsset) -> str:
return Path(asset.local_path).stem.replace("-", " ").replace("_", " ").strip() or "asset"
def render_one(asset: UploadedAsset, *, output: str = "markdown", caption: str | None = None) -> str:
label = caption or default_label(asset)
if output == "json":
return json.dumps(asset.to_dict(), ensure_ascii=False, indent=2)
if output == "url":
return asset.url
if output == "html":
return render_html(asset, label)
if output == "markdown":
return render_markdown(asset, label)
raise ValueError(f"Unsupported output format: {output}")
def render_many(assets: list[UploadedAsset], *, output: str = "markdown", caption: str | None = None) -> str:
if output == "json":
return json.dumps([asset.to_dict() for asset in assets], ensure_ascii=False, indent=2)
return "\n\n".join(render_one(asset, output=output, caption=caption) for asset in assets)
def render_markdown(asset: UploadedAsset, label: str) -> str:
safe_label = label.replace('\\', '\\\\').replace('[', '\\[').replace(']', '\\]').replace('\n', ' ')
safe_url = quote(valid_url(asset.url), safe=':/?#%&=+@,;~.-_')
if asset.kind == "image":
return f""
if asset.kind in {"audio", "video"}:
return render_html(asset, label)
return f"[{safe_label}]({safe_url})"
def valid_url(url: str) -> str:
parsed = urlsplit(url)
if parsed.scheme not in {'https', 'http'} or not parsed.netloc or parsed.username or parsed.password:
raise ValueError('Expected an HTTP(S) asset URL without embedded credentials.')
return url
def render_html(asset: UploadedAsset, label: str) -> str:
label = escape(label, quote=True)
url = escape(valid_url(asset.url), quote=True)
if asset.kind == "image":
return (
"\n"
f'
\n'
f" {label}\n"
""
)
if asset.kind == "audio":
return (
"\n"
f' \n'
f" {label}\n"
""
)
if asset.kind == "video":
return (
"\n"
f' \n'
f" {label}\n"
""
)
return f'{label}'