Перейти к содержимому

23. Встраивание диаграмм

Хостируемый Viewer на archlang.dev/demo хорош для “вставил — посмотрел”. Для дашбордов, ADR, внутренних порталов и маркетинговых страниц вам нужны диаграммы на собственных страницах. Ответ — пользовательский элемент <archlang-viewer>: один тег <script>, один пользовательский элемент, и диаграмма появляется.

В этой главе разбираются атрибуты элемента, встроенный исходник, многофайловый сценарий, собственный хостинг, тематизация и протокол событий, которые Viewer возвращает вашей странице.

Правило. То, что вы встраиваете, — это выводимое представление исходника .arch, а не рисунок, который вы поддерживаете отдельно. Текст — источник истины; диаграмма отрисовывается из него при каждой загрузке. Поэтому встраивание всегда отражает модель — нет картинки, которую нужно вручную держать синхронной, и нечего перерисовывать. Держите модель точной, и встраивание остаётся точным.

Один .arch файл, загруженный с URL:

<script type="module" src="https://archlang.dev/viewer/archlang-viewer.js"></script>
<archlang-viewer
src="./checkout.arch"
style="width: 100%; height: 480px">
</archlang-viewer>

И всё. Скрипт регистрирует пользовательский элемент. Элемент загружает ./checkout.arch, парсит его, отрисовывает диаграмму внутри изолированного через shadow DOM iframe. Диаграмма интерактивна — панорамирование, зум, клик по узлам, наведение для деталей. Применяется всё поведение LOD из Главы 20.

Основное представление остаётся чистым: оно показывает граф бизнес-вызовов, а не транспортную обвязку под ним. Инфраструктурные планы — брокер сообщений, сетевая зона, логи, метрики — моделируются как аспекты (разделяемые классификации), и Viewer раскрывает их как слои-оверлеи по требованию. Читатель переключает раскладку аспекта брокера, чтобы увидеть, какие вызовы идут через какой брокер, затем выключает её обратно; план данных проявляется только по запросу, так что встроенная диаграмма никогда не топит свою аудиторию в инфраструктуре, за которой та не приходила (Глава 9).

Когда исходник — часть самой страницы (например, встроен в Markdown-пост), используйте паттерн дочернего инлайн-скрипта:

<archlang-viewer style="width: 100%; height: 480px">
<script type="text/arch" data-path="/main.arch">
service Orders {
aspect team: "Commerce"
rest_create createOrder
rest_read getOrder
}
service Inventory {
aspect team: "Commerce"
}
</script>
</archlang-viewer>

<script type="text/arch"> не выполняется браузером — его содержимое читается Viewer. Атрибут data-path именует путь внутри рабочего пространства, по которому файл должен оказаться.

Без явного package.archspace Viewer вставляет дефолтный, который импортирует arch.backend и arch.extras, чтобы разрешались стандартные типы. Это поведение управляется wrap-manifest (ниже).

Встроенный исходник — многофайловое рабочее пространство

Заголовок раздела «Встроенный исходник — многофайловое рабочее пространство»

Для рабочих пространств с несколькими файлами объявите каждый со своим <script>:

<archlang-viewer
wrap-manifest="false"
style="width: 100%; height: 600px">
<script type="text/arch" data-path="/package.archspace">
package: my.shop
use service, rest_create from arch.backend
</script>
<script type="text/arch" data-path="/orders.arch">
service Orders {
aspect team: "Commerce"
rest_create createOrder
}
</script>
<script type="text/arch" data-path="/payments.arch">
service Payments {
aspect team: "Payments"
rest_create authorize
}
</script>
</archlang-viewer>

wrap-manifest="false" отключает автоматическую вставку манифеста, потому что вы предоставляете свой. Используйте это всегда, когда у вас несколько файлов или вы хотите не-дефолтные импорты.

АтрибутПо умолчаниюЭффект
src(нет)URL для загрузки одного .arch файла. Загружается как /main.arch в рабочем пространстве.
hostOrigin, с которого пришёл archlang-viewer.jsБазовый URL развёрнутого iframe Viewer. Переопределите при собственном хостинге.
wrap-manifest"true"Когда true и package.archspace отсутствует, Viewer вставляет дефолтный. Установите "false", когда передаёте свой манифест.

Элемент расширяет HTMLElement, поэтому стандартное CSS-сайзинг (style, class) применяется как обычно. iframe живёт внутри shadow root, так что CSS вашей страницы не сможет случайно его застилизовать.

Элемент пробрасывает три CustomEvent для интеграции со страницей-хостом:

СобытиеdetailКогда
arch-ready{}Встроенный iframe закончил инициализацию. Viewer готов принять исходник.
arch-loaded{ moduleCount }Рендер успешно завершился. moduleCount — число разрешённых модулей.
arch-error{ message }Ошибка парсинга или разрешения. message — текст диагностики.
const v = document.querySelector("archlang-viewer");
v.addEventListener("arch-ready", () => console.log("viewer up"));
v.addEventListener("arch-loaded", (e) => console.log("rendered", e.detail.moduleCount, "modules"));
v.addEventListener("arch-error", (e) => console.error("arch error:", e.detail.message));

События — это поверхность интеграции для телеметрии, отчётов об ошибках и индикаторов статуса на странице.

По умолчанию атрибут host равен origin, с которого пришёл archlang-viewer.js. То есть если вы отдаёте скрипт со своего деплоя на https://internal.example.com/arch/archlang-viewer.js, iframe автоматически загружается с того же origin.

Чтобы разделить: отдавайте скрипт с одного origin, а Viewer запускайте на другом:

<script type="module" src="/static/archlang-viewer.js"></script>
<archlang-viewer
host="https://viewer.internal.example.com"
src="./diagram.arch"
style="width: 100%; height: 480px">
</archlang-viewer>

Сборка Viewer — это одно статическое SPA: положите dist/ из @archlang/viewer в S3-бакет или за nginx — и готово. Никакого рендеринга на стороне сервера, никакого SSR-бэкенда.

Элемент отрисовывает iframe на 100% ширины и 100% высоты самого себя. Задавайте размер элемента так же, как любому другому блочному элементу:

<archlang-viewer style="width: 100%; height: 60vh"></archlang-viewer>
<archlang-viewer class="my-diagram-grid-cell"></archlang-viewer>
.my-diagram-grid-cell { width: 100%; aspect-ratio: 16 / 9; }

Рендерер Viewer перетекает при изменении размеров хоста. В узких лейаутах правила LOD предпочитают компактный зум; в широких — всё расходится.

Тема Viewer по умолчанию соответствует хостируемому демо. Своя тематизация для виджетов, поставляемых внутри вашего пакета, работает через CSS-утилиты arch-* (Глава 20) — те же утилиты UnoCSS работают и во встроенном Viewer, потому что обе поверхности потребляют одну и ту же скомпилированную CSS.

Кросс-origin тематизация самого встраивания (переопределение токенов --au-* с хост-страницы) требует, чтобы хост и Viewer разделяли origin: пользовательские CSS-свойства не наследуются через границы iframe. Хостируйте Viewer на том же origin, что и хост-страницу, чтобы дать ему доступ к вашей CSS.

  • Для README.md на GitHub — GitHub вырезает теги <script>. Встраиванию нужен JavaScript для рендера.
  • Для слайдовой презентации — та же проблема. Диаграмме нужен живой браузер.
  • Для письма — нет среды исполнения JavaScript.

Для поверхностей, не способных запускать встраивание, есть два пути. Отрисуйте диаграмму на этапе сборки и закоммитьте изображение рядом с исходником .arch — эндпоинт скриншотов хостируемого Viewer и headless-рендеры из @archlang/render практичнее всего. Либо, когда нужна не картинка, а весь интерактивный Viewer, выгрузите самодостаточный файл:

Окно терминала
archlang export html . -o architecture.html

Один HTML-файл с оболочкой, моделью и шрифтами внутри; открывается офлайн без развёрнутого Viewer (глава 21). Годится, чтобы отправить архитектуру письмом, приложить к ревью или положить в релиз. Это снимок — он не обновляется вслед за моделью, и ровно для этого существует встраивание.

Встраивание — для живых, интерактивных поверхностей: дашбордов, внутренних порталов, ADR-страниц с обратной связью через события.

  • Один тег <script> плюс один элемент <archlang-viewer> отрисовывают диаграмму на любой странице.
  • src для одного загружаемого файла; встроенные дочерние <script type="text/arch" data-path="..."> для многофайловых рабочих пространств.
  • wrap-manifest управляет автоматической вставкой манифеста.
  • host переопределяет origin iframe; по умолчанию — тот же origin, с которого пришёл скрипт.
  • События arch-ready, arch-loaded, arch-error интегрируют Viewer с телеметрией страницы-хоста.
  • Стилизация виджетов переиспользует CSS-утилиты arch-* из Главы 20.

Глава 24: Библиотечные API → — нижележащие пакеты (@archlang/engine, @archlang/lsp, @archlang/render) для авторов инструментов.