Наследие в картинках: Как мы рисовали PNG-диаграммы на бэкенде
· 3 min read
Настроить файловую структуру через sidebar.toml было только половиной дела. Вторым жестким требованием для успешной миграции на работе было наличие визуальных диаграмм наследования (Class Hierarchy).

Проблема заключалась в том, что старый генератор выдавал эти диаграммы не в виде модного интерактивного веб-компонента, а в виде обычных, статичных PNG-картинок, вшитых прямо в HTML-код.
Почему не современный JS?
логичным решением было бы отдать древовидную JSON-структуру на фронтенд и отрендерить красивый интерактивный граф с помощью Mermaid.js или React Flow.
Но у нас были жесткие ограничения. Сгенерированная документация должна была уметь работать в том числе и в оффлайне, мгновенно грузиться без тяжелых JS-бандлов и, главное, визуально совпадать со старым корпоративным стилем. Решение оставалось только одно: рисовать настоящие PNG-файлы прямо во время сборки на стороне бэкенда.
Пиксель-арт на Pillow
Мы затащили в пайплайн библиотеку Pillow.
Генерация графики на стороне сервера — это тот еще квест. Нам пришлось писать логику обхода AST, которая брала список предков класса и программно рисовала их на виртуальном холсте. Мы вручную высчитывали размеры шрифта, координаты каждого прямоугольника, отступы и рисовали соединительные линии со стрелочками. Это была кропотливая работа с графическими примитивами внутри сурового движка генерации документации.
Ад регрессионного тестирования

Самое веселое началось, когда мы покрыли этот функционал регрессионными тестами. В нашем CI-пайплайне тесты на картинки начали непредсказуемо падать.
Изначально мы сравнивали сгенерированные PNG-файлы с эталонными картинками побайтово (raw bytes). Но выяснилась неприятная деталь: байтовый поток сжатия PNG немного отличался в зависимости от операционной системы (Windows на локальной машине vs Linux в CI). Разные версии системной библиотеки zlib сжимали одни и те же пиксели в разный бинарный код.
Визуально картинки были абсолютно идентичны, но хэши файлов разъезжались. Нам пришлось полностью переписать тесты: теперь мы загружали и эталон, и результат через Pillow, раскодировали их и попиксельно сверяли RGBA-матрицы в памяти. Только так тесты позеленели.
Перенос в ядро
Как и в случае с sidebar.toml, изначально мы писали генерацию картинок исключительно как костыль для рабочего плагина.
Но когда алгоритм был отлажен, мы поняли, что сделали классную фичу. Легковесные статичные диаграммы наследования без JS-зависимостей — это объективный плюс для любого проекта. По уже отработанной схеме мы вытащили логику отрисовки графики из закрытого плагина и перенесли её в основное ядро Flude.
Итог
Все рабочие требования были выполнены: и по ссылкам, и по картинкам. Ядро доказало свою гибкость и готовность работать в жестких Enterprise-условиях.
Впереди нас ждал выход за пределы уютного локального окружения. Настало время интегрировать наши CLI-клиенты с популярными CI/CD платформами. О том, как мы теряли переменные окружения в GitLab и боролись с прокси в Bitbucket — читайте в следующем эпизоде.