199 lines
5.9 KiB
Markdown
199 lines
5.9 KiB
Markdown
# Исправление: Поддержка переносов строк в сообщениях
|
||
|
||
**Дата:** 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. ✅ Работает для всех типов сообщений (свои и чужие)
|
||
|
||
---
|
||
|
||
**Статус:** ✅ Исправлено
|
||
**Тестирование:** Требуется проверка в браузере
|