10. Описания
Описание — это голая строка в любом теле: модуля, фасета, интерфейса, проекции, процесса. Рендереры обращаются с текстом описания как с markdown с двумя расширениями: перекрёстные ссылки ([[…]]) и интерполяция меток (@…). Они появляются везде, где показываются описания: всплывающие подсказки, документация автодополнения, боковые панели, тела виджетов.
module Payments { team: Payments
labels { domain: Payments security.zone: PCI }
" # Payments
Core payment processor for the **@domain** domain, operating in the *@security.zone* zone. Published events are consumed by [[Orders]] and [[Notifications]].
> Every transaction in the platform flows through this service. "
interface Authorize interface Refund}Описание рендерится с markdown-форматированием, с подставленными @domain и @security.zone, и с [[Orders]] и [[Notifications]], отрендеренными как кликабельные ссылки на соответствующие модули.
Подмножество markdown
Поддерживаются следующие конструкции CommonMark:
| Конструкция | Пример |
|---|---|
| Жирный | **bold** |
| Курсив | *italic* |
| Зачёркивание | ~~struck~~ |
| Встроенный код | `code` |
| Заголовки | # H1, ## H2, ### H3 |
| Списки | упорядоченные, неупорядоченные, вложенные |
| Таблицы | таблицы на вертикальных чертах в стиле GFM |
| Цитаты | > note |
| Блоки кода | огороженные тройными обратными кавычками, опционально с языком |
| Горизонтальная линия | --- |
| Внешние ссылки | [text](https://...) |
Следующее не поддерживается и либо рендерится как литеральный текст, либо вырезается:
- Сырой HTML (граница безопасности — рендереры агрессивно очищают).
- Изображения (описания — это текст; визуальное место в виджетах и проекциях).
- Сноски, списки определений, списки задач.
- Автоматическое связывание голых URL (используйте явное
[text](url)).
Один ранг заголовков
Заголовки (#, ##, ###) все рендерятся с одинаковым визуальным рангом. У описаний один уровень заголовков; глубина не несёт семантического веса. Вы вольны использовать несколько # для читаемости исходника, но не полагайтесь на визуальную иерархию между H1 и H3.
Причина: описания появляются во всплывающих подсказках, боковых панелях и других стеснённых контекстах, где воспроизведение полной иерархии документа выглядит неуместно. Воспринимайте заголовки как названия разделов, а не как вложенность.
Перекрёстные ссылки: [[…]]
[[…]] ссылается на другое объявление в модели. Две формы:
По стабильному идентификатору:
"Routes to [[#pay002]] for downstream processing."Всегда разрешается, если цель существует в рабочем пространстве. Рендерится как человекочитаемое имя цели, связанное с местом её объявления.
По человекочитаемому имени:
"Published events are consumed by [[Orders]] and [[Notifications]]."Разрешается по всему рабочему пространству. Если два объявления имеют общее имя, ссылка неоднозначна — рендерер помечает её как ошибку, а LSP выдаёт диагностику с перечислением кандидатов. Снимите неоднозначность, переключившись на форму с идентификатором.
Имена могут быть с пространством имён; форма с пространством имён сопоставляется целиком:
"See [[Personal.Banking.Payments]] for the legacy path."Ссылки, которые не разрешаются, рендерятся как маркеры ошибки и выдают предупреждения LSP — опечатки всплывают сразу, а не гниют молча.
Интерполяция меток: @…
@labelPath подставляет значение метки, объявленной на (или каскадированной в) тот же узел, к которому прикреплено описание. Путь зеркалит форму квалифицированного имени, используемую в labels { }:
module Payments { labels { domain: Payments sla.tier: gold }
"Owned by @team. SLA tier: @sla.tier. Operates in @domain."}Рендерится примерно как: «Owned by Payments. SLA tier: gold. Operates in Payments.»
Разрешение идёт по цепочке типов — если узел не объявляет метку сам, но наследует её от родительского типа, используется унаследованное значение.
Локальная область видимости
@ читает метки на владеющем узле, никогда — на узлах, на которые есть ссылки:
module A { labels { domain: Sales } "Domain: @domain" // resolves to "Sales"}
module B { labels { domain: Ops } "Other module's domain: @domain" // resolves to "Ops" (B's own label), // NOT A's domain}Описание на модуле A не может читать метки на модуле B. Для межузлового доступа используйте [[B]] — но ссылка не интерполирует.
Отсутствующие метки всплывают
Если @labelPath не разрешается, рендерер выводит литеральную метку-страж <missing:labelPath>, а LSP выдаёт предупреждение в месте интерполяции. Тихий откат к пустой строке запрещён — опечатки и устаревшие ссылки обязаны быть видимы.
module C { "Owner: @owner" // no 'owner' label declared or inherited}Рендерится как: «Owner: <missing:owner>» с предупреждением LSP.
Несколько описаний склеиваются
В теле может быть несколько голых строк. Они соединяются через \n в порядке объявления:
module Payments { "First paragraph about the service."
team: Payments
"Second paragraph, declared after the team field. Order in the source doesn't matter for resolution but does matter for description joining."
interface Authorize}Это позволяет длинным описаниям охватывать несколько строковых литералов, не вынуждая использовать одну гигантскую многострочную строку.
Разобранный пример
Реальное описание из демо Payments:
module #pay001 Payments { team: Payments
labels { domain: Payments security.zone: PCI criticality: High }
" Core **payment processing** service for the *@domain* domain. Operates in the `@security.zone` zone with criticality *@criticality*.
> Every transaction in the platform flows through this service > before reaching an external processor.
**Capabilities.** Authorize, capture, and refund transactions; route to processors via [[#pay002]]; publish `PaymentEvents` consumed by [[Orders]] and [[Notifications]].
**Compliance.** PCI-DSS scope. See the [internal runbook](https://wiki.acme.com/pci). "
interface Authorize interface Refund interface PaymentEvents}Это рендерится как полная markdown-карточка с подстановками меток и живыми перекрёстными ссылками на #pay002, Orders и Notifications.
Где живёт резолвер
Резолвер перекрёстных ссылок и интерполятор меток — часть пакета core, а не только LSP. И LSP (для диагностик и всплывающих подсказок), и клиентские просмотрщики (для рендеринга) используют один и тот же резолвер. Итог: описания выглядят идентично везде, где они показываются.
Итоги
- Описания — голые строки, обрабатываемые как markdown с двумя расширениями Archlang.
[[#id]]и[[Name]]ссылаются на другие объявления.@labelPathподставляет значение метки на том же узле.- Заголовки все рендерятся с одним рангом; сырой HTML и изображения не поддерживаются.
- Отсутствующие ссылки и отсутствующие пути меток всплывают как ошибки, никогда не тихо.
- Несколько описаний голыми строками склеиваются.
Что дальше
Глава 11: Стандартная библиотека → — от базовых видов к service, command, event и остальной лексике стандартной библиотеки.