mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 09:55:03 +00:00
rss-formatting-preserve: сохранять абзацы и разметку из RSS (html_to_text/extract_full_text normalize; safe_html bleach для предпросмотра; пересборка старых постов)
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# rss-formatting-preserve: сохранять форматирование RSS-новостей (абзацы, разметка)
|
||||
|
||||
## Why
|
||||
|
||||
Пользователь: в RSS omarchy внутри текста новости есть HTML-символы, а мы их «выкидываем»
|
||||
из текста, из-за чего вся новость в предпросмотре отображается сплошным текстом, ничего
|
||||
не понять. Нужно при скачивании из источников RSS сохранять заложенное форматирование.
|
||||
|
||||
Разбор:
|
||||
- `html_to_text()` (crawler/rss_crawler.py) режет HTML корректно, но без разделителей
|
||||
между блочными элементами (p/li/h1-6/blockquote) — абзацы/списки сливаются в один кусок.
|
||||
- После этого `re.sub(r"\s+", " ", text)` (стр. 143) схлопывает и переносы строк —
|
||||
даже если бы были `\n\n`, они превращаются в один пробел. Итог: «сплошной текст».
|
||||
- В вебе `md_filter` (web/app.py) вызывается на `text` из RSS — синтаксис HTML (b/i/a)
|
||||
экранируется и виден как текст-каша, а markdown-разметки в RSS-тексте нет.
|
||||
|
||||
## Design
|
||||
|
||||
### 1. Краулер: сохранять структуру абзацев
|
||||
|
||||
`html_to_text()`:
|
||||
- после удаления script/style/noscript — вставлять переносы-разделители вокруг блочных
|
||||
тегов (p, div, li, h1–h6, blockquote, pre, tr), чтобы они давали `\n\n` между абзацами
|
||||
и `\n` внутри list-item.
|
||||
- текст по-прежнему plain (в БД хранится текст, а не HTML) — просто читаемая структура.
|
||||
|
||||
`parse_entries()` (стр. 143): заменить `re.sub(r"\s+", " ", text)` на нормализацию:
|
||||
- схлопывать 3+ переноса до 2 (максимум пустая строка между абзацами);
|
||||
- убирать горизонтальные пробелы в начале/конце строк и перед переносами;
|
||||
- пробелы внутри строки НЕ трогать (сохраняются слова/URL).
|
||||
|
||||
### 2. Веб: безопасный рендер HTML-разметки из RSS
|
||||
|
||||
Исходный текст поста (RSS) в предпросмотре (кандидаты, отобранные) — рендерить как
|
||||
безопасный HTML подмножеством тегов, а не экранировать в тёмную кашу:
|
||||
|
||||
- новый фильтр `safe_html` в web/app.py на основе `bleach`:
|
||||
`bleach.clean(text, tags=ALLOWED, attributes={'a': ['href', 'title']},
|
||||
protocols=['http','https'])` + `bleach.linkify`;
|
||||
- применяется ТОЛЬКО к `text` (оригинал из RSS) в candidates.html и selected.html;
|
||||
- markdown-фильтр (`md_filter`) остаётся для пересказов/комментариев (markdown от модели).
|
||||
|
||||
Публикация (publisher/card.py) не меняется: в канал уходит plain text, абзацы `\n\n`
|
||||
будут сохранены — Telegram корректно отобразит переносы.
|
||||
|
||||
### Безопасность
|
||||
|
||||
- `safe_html` — allowlist-санитайзер (bleach): никаких script/style/iframe/on*, href
|
||||
только http(s), linkify распознаёт ссылки. XSS-поверхности нет.
|
||||
- `md_filter` не меняется (остаётся escape→markdown).
|
||||
|
||||
## Files
|
||||
|
||||
- crawler/rss_crawler.py — html_to_text(), parse_entries() (абзацы, нормализация).
|
||||
- web/app.py — фильтр safe_html (bleach).
|
||||
- web/templates/candidates.html — `{{ selected.text | safe_html }}`.
|
||||
- web/templates/selected.html — `{{ selected.text | safe_html }}`.
|
||||
- requirements.txt — +bleach.
|
||||
Reference in New Issue
Block a user