Corp/MESSAGE_NEWLINES_FIX.md

199 lines
5.9 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.

# Исправление: Поддержка переносов строк в сообщениях
**Дата:** 4 декабря 2025 г.
**Проблема:** Сообщения не отображали переносы строк (многострочный текст показывался одной строкой)
---
## 🔴 Проблема
При отправке многострочных сообщений в чате (с нажатием Enter для переноса строки), текст отображался одной строкой, игнорируя все переносы.
### Пример:
**Ввод пользователя:**
```
Строка 1
Строка 2
Строка 3
```
**Отображалось как:**
```
Строка 1 Строка 2 Строка 3
```
---
## 🔍 Анализ
### 1. Рендеринг сообщений (`messageRenderer.js`)
```javascript
// Строка 210
${msg.content ? `<div>${this.escapeHtml(msg.content)}</div>` : ''}
// Метод escapeHtml (строка 318)
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
```
Метод `escapeHtml()` корректно экранирует HTML, но переносы строк (`\n`) остаются в виде символов, которые браузер игнорирует в обычном режиме отображения.
### 2. CSS стили bubble (`chat-detail.css`)
```css
.bubble {
border-radius: 16px;
padding: var(--space-1) var(--space-2);
word-break: break-word;
/* white-space не указан - по умолчанию: normal */
box-shadow: 0 1px 2px rgba(0, 0, 0, .06);
}
```
По умолчанию `white-space: normal` схлопывает последовательные пробелы и переносы строк в один пробел.
---
## ✅ Решение
Добавлено CSS свойство `white-space: pre-wrap` для класса `.bubble`:
```css
.bubble {
border-radius: 16px;
padding: var(--space-1) var(--space-2);
word-break: break-word;
white-space: pre-wrap; /* ← ДОБАВЛЕНО */
box-shadow: 0 1px 2px rgba(0, 0, 0, .06);
}
```
### Что делает `white-space: pre-wrap`:
| Свойство | Переносы строк | Пробелы | Перенос текста |
|----------|---------------|---------|----------------|
| `normal` (по умолчанию) | ❌ Игнорируются | ❌ Схлопываются | ✅ Есть |
| `pre` | ✅ Сохраняются | ✅ Сохраняются | ❌ Нет |
| **`pre-wrap`** | **✅ Сохраняются** | **✅ Сохраняются** | **✅ Есть** |
| `pre-line` | ✅ Сохраняются | ❌ Схлопываются | ✅ Есть |
`pre-wrap` — идеальный вариант для чатов:
- ✅ Сохраняет переносы строк
- ✅ Сохраняет множественные пробелы (для форматирования)
- ✅ Автоматически переносит длинные строки (не вылезает за пределы)
---
## 🎨 Результат
### До исправления:
```
Привет! Как дела? Давно не виделись!
```
### После исправления:
```
Привет!
Как дела?
Давно не виделись!
```
---
## 🧪 Тестирование
### Примеры для тестирования:
1. **Простой перенос:**
```
Строка 1
Строка 2
```
2. **Множественные переносы:**
```
Строка 1
Строка 2 (после двух пустых строк)
```
3. **Длинная строка с переносом:**
```
Очень длинная строка текста, которая должна автоматически перенестись на новую строку если не помещается в ширину bubble
```
4. **Форматированный текст:**
```
Список покупок:
- Молоко
- Хлеб
- Масло
```
5. **Код или табуляция:**
```
function hello() {
console.log("Hello!");
}
```
---
## 📁 Изменённые файлы
- ✅ `backend/static/css/components/chat-detail.css` - добавлен `white-space: pre-wrap` для `.bubble`
---
## 🔄 Альтернативные решения (не использовались)
### Вариант 2: Конвертация `\n` в `<br>` в JavaScript
```javascript
// В messageRenderer.js
formatContent(text) {
return this.escapeHtml(text).replace(/\n/g, '<br>');
}
// Использование:
${msg.content ? `<div>${this.formatContent(msg.content)}</div>` : ''}
```
**Недостатки:**
- ❌ Не сохраняет множественные пробелы
- ❌ Требует изменения JS кода
- ❌ Менее гибко для будущих доработок
### Вариант 3: CSS `white-space: pre-line`
```css
.bubble {
white-space: pre-line;
}
```
**Недостатки:**
- ❌ Не сохраняет множественные пробелы (схлопывает в один)
- ❌ Менее удобно для форматированного текста
---
## 🎯 Выводы
1. ✅ **CSS решение** (`white-space: pre-wrap`) — наиболее правильное и простое
2. ✅ Не требует изменений в JavaScript
3. ✅ Поддерживает все виды форматирования текста
4. ✅ Совместимо с существующей логикой экранирования HTML
5. ✅ Работает для всех типов сообщений (свои и чужие)
---
**Статус:** ✅ Исправлено
**Тестирование:** Требуется проверка в браузере