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

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

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

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

Самый простой случай

Один .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.

Встроенный исходник — один файл

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

<archlang-viewer style="width: 100%; height: 480px">
<script type="text/arch" data-path="/main.arch">
service Orders {
team: Commerce
command CreateOrder
query GetOrder
}
service Inventory {
team: Commerce
}
</script>
</archlang-viewer>

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

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

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

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

<archlang-viewer
wrap-manifest="false"
style="width: 100%; height: 600px">
<script type="text/arch" data-path="/package.archspace">
name: my.shop
use * from arch.modules
use * from arch.kinds
</script>
<script type="text/arch" data-path="/orders.arch">
service Orders {
team: Commerce
command CreateOrder
}
</script>
<script type="text/arch" data-path="/payments.arch">
service Payments {
team: Payments
command 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/web в 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/web — два практичных пути.

Встраивание — для живых, интерактивных поверхностей: дашбордов, внутренних порталов, 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/parser, @archlang/core, @archlang/lsp) для авторов инструментов.