Наследие в картинках: Как мы рисовали PNG-диаграммы на бэкенде

 · 3 min read

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

Legacy Png Diagrams Pillow

Проблема заключалась в том, что старый генератор выдавал эти диаграммы не в виде модного интерактивного веб-компонента, а в виде обычных, статичных PNG-картинок, вшитых прямо в HTML-код.

Почему не современный JS?

логичным решением было бы отдать древовидную JSON-структуру на фронтенд и отрендерить красивый интерактивный граф с помощью Mermaid.js или React Flow.

Но у нас были жесткие ограничения. Сгенерированная документация должна была уметь работать в том числе и в оффлайне, мгновенно грузиться без тяжелых JS-бандлов и, главное, визуально совпадать со старым корпоративным стилем. Решение оставалось только одно: рисовать настоящие PNG-файлы прямо во время сборки на стороне бэкенда.

Пиксель-арт на Pillow

Мы затащили в пайплайн библиотеку Pillow.

Генерация графики на стороне сервера — это тот еще квест. Нам пришлось писать логику обхода AST, которая брала список предков класса и программно рисовала их на виртуальном холсте. Мы вручную высчитывали размеры шрифта, координаты каждого прямоугольника, отступы и рисовали соединительные линии со стрелочками. Это была кропотливая работа с графическими примитивами внутри сурового движка генерации документации.

Ад регрессионного тестирования

Legacy Png Diagrams Pillow Part 2

Самое веселое началось, когда мы покрыли этот функционал регрессионными тестами. В нашем CI-пайплайне тесты на картинки начали непредсказуемо падать.

Изначально мы сравнивали сгенерированные PNG-файлы с эталонными картинками побайтово (raw bytes). Но выяснилась неприятная деталь: байтовый поток сжатия PNG немного отличался в зависимости от операционной системы (Windows на локальной машине vs Linux в CI). Разные версии системной библиотеки zlib сжимали одни и те же пиксели в разный бинарный код.

Визуально картинки были абсолютно идентичны, но хэши файлов разъезжались. Нам пришлось полностью переписать тесты: теперь мы загружали и эталон, и результат через Pillow, раскодировали их и попиксельно сверяли RGBA-матрицы в памяти. Только так тесты позеленели.

Перенос в ядро

Как и в случае с sidebar.toml, изначально мы писали генерацию картинок исключительно как костыль для рабочего плагина.

Но когда алгоритм был отлажен, мы поняли, что сделали классную фичу. Легковесные статичные диаграммы наследования без JS-зависимостей — это объективный плюс для любого проекта. По уже отработанной схеме мы вытащили логику отрисовки графики из закрытого плагина и перенесли её в основное ядро Flude.

Итог

Все рабочие требования были выполнены: и по ссылкам, и по картинкам. Ядро доказало свою гибкость и готовность работать в жестких Enterprise-условиях.

Впереди нас ждал выход за пределы уютного локального окружения. Настало время интегрировать наши CLI-клиенты с популярными CI/CD платформами. О том, как мы теряли переменные окружения в GitLab и боролись с прокси в Bitbucket — читайте в следующем эпизоде.