Files
vesti/openspec/changes/archive/2026-09-13-web-render-markdown/proposal.md
T

34 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Why
В списке кандидатов (`web/templates/candidates.html:41`) текст поста выводится как есть:
```html
<div class="post-text mt-2">{{ (p.text or '')[:500] }}</div>
```
Jinja2 экранирует HTML-сущности (`{{ }}` — автоэскейп), но **не парсит markdown**: жирный
текст, ссылки, списки, заголовки в исходных постах (телеграм-посты с markdown-разметкой)
отображаются сырыми символами `**`, `[text](url)`, `- item`. Пользователь видит «сырой
markdown, а не красивый».
## What Changes
- Рендерить текст поста из markdown в HTML перед выводом в списке кандидатов.
- Добавить Jinja2-фильтр `markdown` (или `md`): `{{ (p.text or '')[:2000] | markdown }}`.
- Использовать локальную Python-библиотеку (не JS/CDN!): `markdown` (Python-Markdown) —
уже покрывает жирный/курсив/ссылки/списки/заголовки. Безопасный вывод: экранирование
HTML-тегов в исходном тексте (вход — непроверенный текст из TG), `nl2br`/`pre`-обёртка
для переносов строк.
- Только серверный рендер, без внешних JS-библиотек (в духе deexternalize-web-assets).
- Превратить `.post-text` в блок с классом `post-text` и `white-space` нормальным
(не `pre-wrap` над сырым md) или оставить, но уже с HTML.
## Impact
- Файлы: `web/app.py` (зарегистрировать фильтр), `web/templates/candidates.html`
(заменить вывод), возможно `published.html` (если там тоже текст).
- Зависимость: добавить `Markdown>=3.6` в `requirements.txt` (pip, локально).
- Безопасность: важно экранировать HTML до передачи в markdown-парсер (иначе XSS из
telegram-постов).
- Минимальная правка; поведение страниц не меняется, кроме вида текста.
- Rollback: вернуть `{{ (p.text or '')[:500] }}`, убрать фильтр.