mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 09:55:03 +00:00
61 lines
2.3 KiB
Markdown
61 lines
2.3 KiB
Markdown
## Дизайн
|
||
|
||
### 1. Зависимость
|
||
|
||
```bash
|
||
/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) добавить:
|
||
|
||
```python
|
||
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:
|
||
|
||
```jinja
|
||
<div class="post-text mt-2">{{ (p.text or '')[:500] }}</div>
|
||
```
|
||
|
||
на:
|
||
|
||
```jinja
|
||
<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). |