- Создана структура docs/ с категориями: completed, guides, architecture, diagnostic, in-progress, reports - Перемещено 47+ MD файлов из корня проекта в docs/ - Удалено 6 устаревших/дублирующихся файлов - Создана структура backend/scripts/ для тестов и утилит - Перемещено 35 Python скриптов в backend/scripts/ - Создана структура backend/docs/ для технической документации - Перемещено 12 MD файлов backend в backend/docs/ - Перемещены LDAP тестовые данные в backend/tests/fixtures/ - Добавлены README файлы для навигации - Добавлены правила в .github/copilot-instructions.md для размещения документации Результат: - Корень проекта: только README.md - Корень backend/: только manage.py и Django приложения - Вся документация организована в структурированные папки
5.9 KiB
Исправление: Поддержка переносов строк в сообщениях
Дата: 4 декабря 2025 г.
Проблема: Сообщения не отображали переносы строк (многострочный текст показывался одной строкой)
🔴 Проблема
При отправке многострочных сообщений в чате (с нажатием Enter для переноса строки), текст отображался одной строкой, игнорируя все переносы.
Пример:
Ввод пользователя:
Строка 1
Строка 2
Строка 3
Отображалось как:
Строка 1 Строка 2 Строка 3
🔍 Анализ
1. Рендеринг сообщений (messageRenderer.js)
// Строка 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)
.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:
.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 Строка 2 -
Множественные переносы:
Строка 1 Строка 2 (после двух пустых строк) -
Длинная строка с переносом:
Очень длинная строка текста, которая должна автоматически перенестись на новую строку если не помещается в ширину bubble -
Форматированный текст:
Список покупок: - Молоко - Хлеб - Масло -
Код или табуляция:
function hello() { console.log("Hello!"); }
📁 Изменённые файлы
- ✅
backend/static/css/components/chat-detail.css- добавленwhite-space: pre-wrapдля.bubble
🔄 Альтернативные решения (не использовались)
Вариант 2: Конвертация \n в <br> в 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
.bubble {
white-space: pre-line;
}
Недостатки:
- ❌ Не сохраняет множественные пробелы (схлопывает в один)
- ❌ Менее удобно для форматированного текста
🎯 Выводы
- ✅ CSS решение (
white-space: pre-wrap) — наиболее правильное и простое - ✅ Не требует изменений в JavaScript
- ✅ Поддерживает все виды форматирования текста
- ✅ Совместимо с существующей логикой экранирования HTML
- ✅ Работает для всех типов сообщений (свои и чужие)
Статус: ✅ Исправлено
Тестирование: Требуется проверка в браузере