diff --git a/README.md b/README.md index 6c06888..ea32b4c 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,9 @@ nginx (https://schedule.our-place.ru) → 127.0.0.1:8090 заменяется на «Окно». - Подпись недели появляется только там, где недели действительно различаются; бейдж «Сейчас» подсвечивает текущую неделю. +- Длинные ссылки в карточке переносятся по служебным символам и каждые + 24 символа (``), поэтому карточка не вылезает за экран даже в старых + браузерах, где нет `overflow-wrap`. - Приложение можно «установить» на главный экран (манифест + service worker + иконки приложения); на iOS иконку берёт `apple-touch-icon`. diff --git a/src/frontend/static/app.js b/src/frontend/static/app.js index 215e903..b7d5ef2 100644 --- a/src/frontend/static/app.js +++ b/src/frontend/static/app.js @@ -239,10 +239,10 @@ function entityLessonHTML(parity, entry) {
${badge} ${entry.marker ? `${escapeHTML(entry.marker)}` : ""} - ${escapeHTML(entry.subject)} + ${withBreaks(entry.subject)}
- ${details.length ? `
${escapeHTML(details.join(" · "))}
` : ""} - ${entry.note ? `
${escapeHTML(entry.note)}
` : ""} + ${details.length ? `
${withBreaks(details.join(" · "))}
` : ""} + ${entry.note ? `
${withBreaks(entry.note)}
` : ""} `; } @@ -277,10 +277,10 @@ function singleLessonHTML(badgeKey, lesson, full) {
${badge} ${lesson.marker ? `${escapeHTML(lesson.marker)}` : ""} - ${escapeHTML(lesson.subject)} + ${withBreaks(lesson.subject)}
- ${details ? `
${escapeHTML(details)}
` : ""} - ${lesson.note ? `
${escapeHTML(lesson.note)}
` : ""} + ${details ? `
${withBreaks(details)}
` : ""} + ${lesson.note ? `
${withBreaks(lesson.note)}
` : ""} `; } @@ -490,6 +490,20 @@ function escapeHTML(s) { return s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c])); } +/** + * Экранирует текст и расставляет точки переноса . + * Длинные ссылки (и вообще слова без пробелов) переносятся в любом браузере — + * не полагаемся на поддержку overflow-wrap: anywhere старыми движками. + */ +function withBreaks(text) { + const WBR = "\u0001"; // служебный маркер, в тексте таблицы не встречается + if (!text) return ""; + const marked = String(text) + .replace(/([/?&=._\-])(?=\S)/g, "$1" + WBR) // после служебных символов ссылок + .replace(/(\S{24})(?=\S)/g, "$1" + WBR); // и не реже, чем каждые 24 символа + return escapeHTML(marked).split(WBR).join(""); +} + function applyTheme(theme) { document.documentElement.setAttribute("data-theme", theme); localStorage.setItem("theme", theme);