mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 01:50:03 +00:00
2.3 KiB
2.3 KiB
Дизайн
1. Зависимость
/opt/vesti/.venv/bin/pip install "Markdown>=3.6"
echo "Markdown>=3.6" >> /opt/vesti/requirements.txt
2. Фильтр в web/app.py
Рядом с существующим tpl.filters["from_json"] (строка 29) добавить:
import markdown as md_lib
from markupsafe import Markup
def md_filter(text: str) -> Markup:
if not text:
return Markup("")
# 1) экранируем HTML (защита от XSS), 2) рендерим markdown, 3) переносы строк
import markupsafe
safe = markupsafe.escape(text)
html = md_lib.markdown(safe, extensions=["nl2br", "sane_lists"])
return Markup(html)
tpl.filters["markdown"] = md_filter
(В Jinja2 по умолчанию Markup не экранируется повторно; markupsafe уже идёт с Jinja2.)
3. Шаблон candidates.html
Заменить строку 41:
<div class="post-text mt-2">{{ (p.text or '')[:500] }}</div>
на:
<div class="post-text mt-2">{{ (p.text or '')[:2000] | markdown }}</div>
И в base.html для .post-text оставить white-space: pre-wrap (после nl2br переносы
строк уже есть, но pre-wrap не помешает) — или сменить на line-height: 1.5.
4. Безопасность
markupsafe.escapeдо markdown-парсера — ссылки[x](javascript:...)должны быть заблокированы. Python-Markdown сам экранирует опасные протоколы в ссылках, но предварительное экранирование — обязательный слой.- Не использовать
|safeбезMarkup.
5. Проверка
- Пост с текстом
**жирный** [ссылка](https://x) - пунктрендерится жирным/ссылкой/списком. - В HTML нет сырых
**,[,](символов разметки (кроме намеренных). - Ввод
<script>alert(1)</script>отображается как текст, не исполняется. published.html— если там естьp.text/p.summary, применить тот же фильтр (grep).