45 lines
1.7 KiB
Python
45 lines
1.7 KiB
Python
"""Предпросмотр шаблонов и сообщений (HTMX)."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import html
|
||
|
||
from fastapi import APIRouter, Request
|
||
from fastapi.responses import HTMLResponse
|
||
|
||
from admin.preview import SAMPLE_CONTEXT
|
||
from admin.security import check_csrf
|
||
from common.texts.render import MAX_MESSAGE_LENGTH, TemplateError, render, validate
|
||
|
||
router = APIRouter(tags=["preview"])
|
||
|
||
|
||
@router.post("/preview", response_class=HTMLResponse)
|
||
async def preview_message(request: Request) -> HTMLResponse:
|
||
"""Отрендерить текст с тестовыми значениями; результат — в sandbox-iframe."""
|
||
form = await request.form()
|
||
check_csrf(request, str(form.get("csrf_token", "")))
|
||
text = str(form.get("text", ""))
|
||
|
||
unknown = validate(text)
|
||
if unknown:
|
||
return HTMLResponse(
|
||
'<p class="text-sm text-red-600">Неизвестные теги: ' + html.escape(", ".join(unknown)) + "</p>"
|
||
)
|
||
|
||
try:
|
||
rendered = render(text, SAMPLE_CONTEXT)
|
||
except TemplateError as exc: # pragma: no cover - validate уже отсекает неизвестные теги
|
||
return HTMLResponse(f'<p class="text-sm text-red-600">{html.escape(str(exc))}</p>')
|
||
|
||
if len(rendered) > MAX_MESSAGE_LENGTH:
|
||
return HTMLResponse(
|
||
f'<p class="text-sm text-red-600">Текст длиннее лимита Telegram: '
|
||
f"{len(rendered)} из {MAX_MESSAGE_LENGTH} символов.</p>"
|
||
)
|
||
|
||
return HTMLResponse(
|
||
'<iframe sandbox class="h-64 w-full rounded border border-slate-200 bg-white" '
|
||
f'srcdoc="{html.escape(rendered, quote=True)}"></iframe>'
|
||
)
|