# Форматирование текста

В комментариях к задачам можно оформлять текст — выделять жирным, добавлять ссылки, создавать списки и многое другое. Для этого используется markdown: специальные символы вокруг текста задают форматирование.

## 1. Поддерживаемое форматирование

Поддерживаемые виды разметки и их доступность на платформах:

| Синтаксис | Результат | Веб: лента | Веб: чат | iOS | Android |
|-----------|-----------|:-:|:-:|:-:|:-:|
| `**текст**` | Жирный | + | + | + | + |
| `__текст__` | Курсив | + | + | + | + |
| `~~текст~~` | Зачёркнутый | + | + | + | + |
| `((текст))` | Подчёркнутый | + | + | + | + |
| `` `текст` `` | Код (моноширинный шрифт) | + | + | + | — |
| `[текст](url)` | Именованная ссылка | + | + | + | + |
| `# текст` … `###### текст` (до шести `#`) | Заголовок — выделяется полужирным как акцент, размер шрифта не меняется | + | + | — | — |
| ` ```...``` ` | Блок кода (с фоном, моноширинный) | + | + | ± | ± |
| `\| a \| b \|`<br>`\| --- \| --- \|`<br>`\| 1 \| 2 \|` | Таблица с заголовком и рамкой. В ленте растягивается по ширине, в чате — с прокруткой. | + | + | — | — |
| `#12345` | Ссылка на задачу по номеру | + | + | + | + |
| `#!12345` | Ссылка на сообщение по его номеру — открывает чат и прокручивает ленту к сообщению | + | + | — | — |
| `@` + имя пользователя | Упоминание пользователя (@-тег) | + | + | + | + |
| URL (`https://...`) | Автоматическая кликабельная ссылка | + | + | + | + |
| Домен без протокола (`yandex.ru`) | Ссылка с `https://`; текст отображения остаётся тем, что написал автор | + | + | + | + |
| Ссылка на Диск | Открывает папку/файл Диска в превью | + | + | — | — |
| `- текст` | Маркированный список. Внутри пункта работает вся разметка абзаца — жирный, курсив, зачёркнутый, код, именованная ссылка, ссылка на задачу, упоминание и голый адрес. Отступ (пробелы или табу) перед `-` делает подпункт — один уровень вложенности | + | + | — | — |
| `1. текст` | Нумерованный список. Пункты сохраняют исходные номера — например, `3. 4. 5.` так и отображаются как `3. 4. 5.`, в том числе после отправки комментария. Внутри пункта работает та же разметка, что в маркированном | + | + | — | — |
| `---` (на отдельной строке) | Горизонтальный разделитель | + | + | — | — |
| `+++` (на отдельной строке, с 2.268.352) | Спойлер — всё, что ниже первого `+++` в комментарии, сворачивается в раскрываемый блок «Показать больше». Повторные `+++` ниже первого отображаются как обычный текст (без вложенности). Старая обёртка `[+][-]` (прежний формат системных комментариев) больше не обрабатывается — если придёт из старой версии, отображается как обычный текст без ошибок. | + | + | — | — Маркер можно поставить вручную, а при вставке из буфера текста длиннее шести строк или больше 500 символов система добавляет его автоматически. |
| Нажатие Enter | Перенос строки | + | + | + | + |

**Ссылки на задачи рядом с разметкой.** Номер задачи вида `#12345` распознаётся как ссылка и в начале строки, и после пробела или в скобках, и сразу после символа разметки или выделенного жирным текста — например, `#12345`, `сообщение #12345`, `(#12345)` или `**жирный**#12345`. Символ разметки при этом сохраняется и не съедается ссылкой; если в сообщении несколько номеров, ссылкой становится каждый.

**Разметка внутри пунктов списка.** В пункте маркированного или нумерованного списка работает та же разметка, что и в обычном тексте: жирный, курсив, зачёркнутый, моноширинный код, именованная ссылка, ссылка на задачу, упоминание и голый адрес. Символов разметки на экране не видно — всё оформляется так же, как в абзаце.

Подпункт получается отступом: поставьте перед `-` или `1.` два пробела или табу — строка станет подпунктом предыдущего пункта. Поддерживается один уровень вложенности. Продолжение пункта набирается с отступом на следующей строке и остаётся внутри пункта; строки при этом не склеиваются в одну. Пустая строка между пунктами список не разрывает, нумерация остаётся исходной: если первый пункт написан как `3.`, список показывается с тройки.

> ⚠️ **Важно:** отступ неразрывными пробелами (частая история при копировании из Word) подпунктом **не** считается — такая строка останется обычной строкой текста. Ставьте обычные пробелы или табу.

Обозначения: **+** — работает; **—** — не отображается, виден исходный текст вместе с символами разметки; **±** — работает частично (на iOS и Android содержимое тройных обратных кавычек показывается моноширинным шрифтом, но без плашки-фона).

> ⚠️ **Важно:** `__текст__` в 1Форме — это **курсив**, не жирный (для жирного используется `**текст**`). Конструкция `((текст))` отображает **подчёркнутый** текст. Со сборки 2.268 («Скульптор») этот диалект одинаково поддерживается и в HTML-комментариях, и в markdown-ветке комментариев ленты и чата, включая списки и таблицы; внутри блоков и фрагментов кода символы остаются текстом.

**Подсветка синтаксиса в блоках кода.** Если сразу после открывающих тройных обратных кавычек указать язык (например, `sql`), блок кода в ленте и чате подсвечивается по синтаксису — при условии, что грамматика этого языка загружена. К ленте и чату подключены `sql`, `csharp` (C#, .NET) и `json`; язык указывается латиницей, регистр не важен — `SQL` и `sql` равнозначны. Без указания языка или для языка, грамматики которого нет, блок отображается как обычный моноширинный текст, без подсветки.

**Дословное сохранение кода и спецсимволов.** Текст внутри блоков кода — и ограждённых тройными обратными кавычками, и строчных в одинарных — сохраняется и отображается строго в исходном виде. Если фрагмент кода содержит HTML-сущности (например, `&lt;`, `&gt;`, `&amp;`) или примеры разметки, система не разворачивает и не декодирует их: получатели увидят в блоке кода именно те символы и последовательности, которые ввёл автор.

**Подсветка приходит не сразу.** Грамматики языков загружаются отдельными частями, независимо от содержимого ленты. Пока нужная грамматика не загружена, блок кода показывается обычным моноширинным текстом, а через мгновение оформляется. Обновлять страницу не нужно — это нормальное поведение, а не ошибка. Если подсветка не появилась вовсе, проверьте, что язык написан латиницей в тройных обратных кавычках.

**Быстрая подстановка `#` к номеру задачи.** Скопируйте номер задачи из шапки её карточки или из мобильной табличной формы (МТФ) и в течение 120 секунд вставьте в поле сообщения (комментарий, чат, соцсеть) — номер автоматически станет ссылкой на задачу вида `#12345`. Подстановка срабатывает только для номера из одних цифр и только при вставке в поле сообщения: в поиске, админке, текстовых ДП, а также при вставке текста с другими символами номер остаётся без изменений. Буфер обмена не меняется — `#` добавляется лишь в момент вставки.

**Ссылка на конкретное сообщение.** В тексте можно написать `#!` и номер сообщения — например, `#!34567890`. Такая запись превращается в ссылку: по нажатию открывается нужный чат, а если сообщение находится в обсуждении, обсуждение раскрывается, лента прокручивается к сообщению и коротко подсвечивает его — так же, как при нажатии на цитату ответа. Если сообщения нет в уже загруженной части ленты, лента подгружает переписку вокруг него. Ссылка работает в веб-интерфейсе — в ленте задачи и в чате; на мобильных `#!12345` остаётся обычным текстом.

Знак `!` отличает ссылку на сообщение от ссылки на задачу: `#12345` по-прежнему открывает карточку задачи, `#!12345` — сообщение. После `#!` номер должен идти без пробела: запись `#! 12345` ссылкой не станет. Внутри блока кода и внутри адресов вида `https://…` такая запись тоже не становится ссылкой. Нажатие с `Ctrl` или `Cmd` открывает сообщение в новой вкладке.

**Выбор задачи из списка по `#`.** В веб-интерфейсе символ `#` в начале слова — в начале поля или после пробела — раскрывает под полем список объектов, как `@` раскрывает список подписчиков. Пока после `#` ничего не набрано, показываются первые пять записей из «Недавних»; при наборе идёт поиск по введённому тексту, а строка списка несёт название объекта, его номер и категорию. Фильтр — одно слово: пробел его завершает и список закрывается, поэтому разметка заголовков (`# текст`) продолжает работать, а второй `#` список не открывает. Если после `#` набрать одни цифры, в выдачу попадают и закрытые задачи.

Выбор строки — щелчком мыши, клавишей `Enter` или `Tab`: подставляется `#номер` и курсор встаёт сразу за добавленным пробелом, чтобы следующий набранный символ не прилипал к ссылке. Стрелки `↑` и `↓` двигают подсветку, `Esc` закрывает список, не выходя из поля; пока список открыт, `Enter` выбирает строку, а не отправляет сообщение.

![Жирный текст в ленте комментариев](https://help.1forma.ru/help-images/comments/text_format_bold.png)
![Курсив через __текст__](https://help.1forma.ru/help-images/comments/text_format_italic.png)
![Зачёркнутый текст](https://help.1forma.ru/help-images/comments/text_format_strikethrough.png)
![Подчёркнутый текст через ((текст))](https://help.1forma.ru/help-images/comments/text_format_underline.png)
![Inline-код моноширинным шрифтом в плашке](https://help.1forma.ru/help-images/comments/text_format_code.png)
![Кликабельная именованная ссылка](https://help.1forma.ru/help-images/comments/text_format_link.png)
![Автоссылка #TaskId на задачу](https://help.1forma.ru/help-images/comments/text_format_task.png)
![Установка связи +#TaskId с задачей](https://help.1forma.ru/help-images/comments/text_format_+task.png)

---

## 2. Ограничения и поддержка на платформах

**Домен без протокола в тексте комментария становится ссылкой.** Написанный без протокола адрес (`yandex.ru`, `docs.service.ru/report?tab=1`) распознаёт сервер и отдаёт клиенту готовую markdown-разметку: ссылка ведёт на `https://<адрес>`, а текст отображения остаётся тем, что написал автор. Разметка собирается один раз на сервере, поэтому веб-лента, веб-чат, приложения iOS и Android показывают одинаковый результат, и клиент разметку не пересобирает.

**Несколько ссылок и готовая разметка.** В одном сообщении могут распознаваться несколько адресов. Адреса с `http://` или `https://`, в том числе с путями и параметрами запроса, обрабатываются как ссылки. Если сервер уже оформил адрес markdown-ссылкой, клиент показывает её без повторной обёртки. Распознавание охватывает домены, удовлетворяющие правилам, а не только популярные зоны из примеров: список зон ведётся по актуальному снимку IANA.

> Ссылкой становятся не любые сочетания с точкой. Домен распознаётся, если его последняя метка входит в актуальный снимок доменных зон IANA, хотя бы одна метка содержит букву, а зона не входит в список расширений-исключений. Это расширения файлов, которые совпадают с доменными зонами и чаще всего встречаются в именах файлов: `zip`, `mov`, `app`, `dev`, `md`, `sh`, `so`, `rs`, `java`, `ai`, `pl`, `ps`, `py`, `map`, `docs`, `video`, а также зоны исходников и сборки `cc`, `pm`, `ml`, `am`, `mk`, `in`, `as`, `sv`, `la`, `gd`, `st`, `to`. Перечень одинаковый для серверной и веб-части распознавания, всего 28 зон. Поэтому обычным текстом остаются:
>
> - даты — `15.02`, `15.02.2024`;
> - дробные числа — `1.5`, `100.505`;
> - IP-адреса — `192.168.0.1`;
> - имена файлов — `business.md`, `main.py`, `архив.zip`, `script.sh`, `Main.java`, `main.cc`, `Module.pm`, `parser.ml`, `Makefile.am`, `rules.mk`, `config.h.in`, `libfoo.la`;
> - фрагменты кода — `function.onload`.
>
> Исключение действует на зону целиком, а не на имя файла: в зонах из списка обычным текстом остаются и настоящие сайты — `site.in`, `example.to`, `site.la` ссылками не становятся. Если такой адрес всё-таки нужен как ссылка, укажите его с протоколом: `https://site.in` обрабатывается как раньше. Перечень конечный: зоны, в него не попавшие, имена файлов по-прежнему превращаются в ссылки.

Завершающие точку, запятую, точку с запятой, вопросительный и восклицательный знаки и закрывающие скобки в ссылку не входят — они остаются в тексте. Адрес электронной почты целиком остаётся текстом и не превращается в ссылку на часть до символа `@`. Ссылки с протоколом (`https://`, `http://`), включая пути и параметры запроса, оформляются как и раньше; уже оформленные вручную markdown-ссылки и HTML-фрагменты сервер не трогает.


В комментариях 1Формы не поддерживаются HTML-теги, встроенные изображения, цитаты, вложенные списки и курсив через одинарную звёздочку; на веб и мобильных клиентах набор отображаемых элементов различается.

- **HTML-теги** (`<br>`, `<b>`, `<p>`, `<div>` и любые другие) — отображаются как обычный текст или игнорируются. Если нужно вставить угловую скобку `<`, она отобразится корректно — система автоматически её экранирует. Разметка из текста очищается перед показом; пример тега или атрибута в сообщении чата больше не ломает отображение остального текста — очищается только сам фрагмент, а переносы строк, ссылки и выделение сохраняются, как в ленте.
- **Изображения в тексте** (`![alt](url)`) — вставить картинку в текст комментария нельзя, только как вложение.
- **Курсив через одинарную звёздочку** (`*текст*`) — не работает. Используй `__текст__`.
- **Цитаты** (`> текст`) — не поддерживаются ни на одном клиенте, символ `>` останется в тексте.
- **Вложенные списки** — в веб-интерфейсе поддерживается один уровень вложенности: пункт с отступом (пробелы или табу) перед `-` или `1.` отображается подпунктом предыдущего пункта, более глубокая вложенность не отрисовывается. Отступ неразрывными пробелами подпунктом не становится — строка остаётся обычной строкой текста. На iOS и Android списки не отображаются вовсе.
- **Незнакомый тег или слово в угловых скобках вне блока кода сохраняется как текст.** Запись вида `List<string>`, `<T>`, `<custom>` — дженерик, XML-имя, плейсхолдер — разметкой не является: она показывается обычным текстом, и весь остальной текст комментария после неё сохраняется полностью. Чтобы показать фрагмент кода дословно, оформляйте его блоком кода — тройными обратными кавычками.

**Что система заменяет пометкой.** Опасные фрагменты вне блоков кода не удаляются, а заменяются видимой пометкой: теги `script`, `iframe`, `img`, `form`, `style` → `⚠ [tag заблокирован]`; атрибуты вида `onclick=`, `onerror=`, `onload=` → `⚠ [атрибут заблокирован]`; ссылки с запрещённой схемой (`javascript:`, `data:`, `vbscript:`, `file:`, `blob:`) и внутренние адреса → `⚠ [ссылка заблокирована]`. Если такие пометки появились, комментарий помечается как содержащий заблокированный контент. Внутри блоков кода не заменяется ничего — код хранится и показывается дословно.
- **Текст в квадратных скобках «склеивается» со ссылкой, стоящей дальше в том же абзаце.** Разбор ссылок жадный: открывающая `[` ищет закрытие не рядом, а по первому `](` в абзаце — и всё между ними становится телом одной ссылки. Наблюдено на комментарии вида `[intake:2126589] Разбор. Причина падения: … реализовано в [2074052](https://ru.1forma.ru/spa/tasks/2074052)`: вся строка отрендерилась одной синей ссылкой, ведущая `[` пропала. Обходится переносом: текст в скобках — отдельным абзацем (пустая строка между ним и абзацем со ссылкой). Одиночные скобки без ссылки в том же абзаце отображаются нормально, поэтому дефект перемежающийся и на коротких сообщениях не виден.

В веб-интерфейсе (лента и чат) поддерживаются все форматы из таблицы выше: жирный, курсив, зачёркнутый, подчёркнутый, код, ссылки, заголовки, блоки кода, таблицы, маркированные и нумерованные списки, разделители, спойлер, упоминания и ссылки на задачи. Оформление одинаковое: лента и чат используют один и тот же обработчик разметки, различается только ширина области — широкая таблица в ленте растягивается, в бабле чата прокручивается по горизонтали.

В мобильном приложении (iOS и Android) поддерживаются: жирный, курсив, зачёркнутый, подчёркнутый, моноширинный текст, именованные ссылки, ссылки на задачи (`#12345`), @-упоминания, обычные URL и переносы строк. Для моноширинного текста на iOS годятся и одиночные обратные кавычки, и тройные; **на Android — только тройные** (одиночные останутся в тексте как символы).

**Не отображаются** на мобильных: ссылки на сообщение (`#!12345`), заголовки, таблицы, маркированные и нумерованные списки, горизонтальный разделитель, спойлер, превью Диска — эти элементы будут показаны как обычный текст с символами разметки. Если сообщение важно читать с телефона, лучше использовать только **жирный**, _курсив_ и моноширинный текст, а списки набирать тире с новой строки.

## Ссылки в тексте комментария

**Схема по умолчанию у ссылок, введённых вручную.** Ссылка, введённая без протокола, сохраняется и открывается по защищённой схеме `https`, а не по открытой: редактор ссылок не подставляет `http`. Так же открывается и справка из меню пользователя — адрес справки ведёт сразу на защищённую схему, без первого запроса открытым текстом. Ссылки, где схема указана автором явно, не переписываются.

Голый адрес в тексте комментария становится ссылкой: домен без протокола получает схему `https`, а сама ссылка канонизируется. Завершающие знаки препинания — точка, запятая, точка с запятой, восклицательный знак, закрывающая скобка или кавычка — в ссылку не входят: они остаются текстом после неё, даже когда адрес стоит в скобках или в кавычках. Знаки внутри адреса, двоеточие с портом и якорь ссылку не разрывают. Часть адреса почты ссылкой не становится: у записи вида `ivan.name@mail.ru` домен — только часть после собаки, а текст перед ней остаётся текстом, поэтому и карточка превью для него не показывается.
