IS
Все эксперименты
живое

Mermaid Sketch — диаграммы, будто нарисованные от руки

Пишешь текст на языке Mermaid — рядом рисуется диаграмма с кривоватыми, «от руки», фигурами. Пресеты я заранее сгенерировал через GPT; в редакторе можно править код и смотреть, как перерисовывается вживую.

лабораторная запись
Зачем делал

Хотел диаграммы, которые не выглядят как строгий корпоративный BPMN, а как набросок в блокноте — так они читаются дружелюбнее и меньше врут о своей точности. Плюс давно хотел потрогать, как из простого текста получается картинка, и связать это с генерацией через GPT.

Что узнал

У Mermaid с 11-й версии есть встроенный режим look: handDrawn — он гоняет фигуры через rough.js, и идеальные прямоугольники превращаются в дрожащие. Отдельная библиотека не нужна. А ещё securityLevel: strict прогоняет итоговый SVG через DOMPurify, так что публичный редактор можно безопасно кормить любым вводом.

Где сломалось

Первая версия дёргала GPT прямо из браузера на каждый рендер — это и деньги на ветер, и открытая дверь для абьюза. Развернул иначе: живого GPT в проде нет вообще. Диаграммы генерирую заранее локальным скриптом (scripts/mermaid-gen.mjs), кладу как пресеты, а страница — чистый клиентский рендер без единого сетевого запроса.

Стек
Mermaidrough.jsOpenAI

Диаграмма как набросок, а не как чертёж

Mermaid — это язык, где диаграмма описывается текстом: пишешь A --> B, получаешь стрелку от A к B. Удобно, но по умолчанию картинка выходит стерильной — ровные прямоугольники, идеальные линии. Такая форма подсознательно обещает точность, которой у наброска на салфетке нет.

С 11-й версии у Mermaid есть режим look: handDrawn: под капотом фигуры прогоняются через rough.js, и линии становятся чуть дрожащими — как будто нарисовано от руки. Ниже — живой редактор. Жми пресеты сверху или правь код слева, картинка перерисовывается сама.

живое демо
Демо загружается…

Причём тут GPT

Примеры в пресетах я не писал руками по буковкам — надиктовал описания и превратил их в Mermaid через GPT (тот же токен, что крутит генерацию TIL-заметок). Но важный момент — где это происходит:

Скрипт до предела прост: берёт описание аргументом, отправляет его в OpenAI с системным промптом «верни строго валидный Mermaid и ничего больше», снимает возможные ```mermaid ограждения и печатает чистый код в консоль. Дальше я вычитываю результат глазами и вставляю новым пресетом.

node --env-file=.env.local scripts/mermaid-gen.mjs "воронка регистрации: заявка, проверка, письмо, готово"

Как рендер устроен внутри

Ключевых деталей три:

  • Ленивость. mermaid — библиотека немаленькая, поэтому весь компонент грузится динамическим import() и монтируется только когда доскроллил до демо. На главной странице лабы её байтов нет вовсе.
  • Тема. Рендер читает data-themedata-alien) с <html> и через MutationObserver перерисовывается при переключении — набросок живёт и в светлой, и в тёмной, и в «инопланетной» теме сайта.
  • Ошибки. Перед рендером код проходит mermaid.parse(); если синтаксис битый — показываю аккуратную ошибку, но последнюю удачную картинку с экрана не убираю, чтобы не мигало пустотой на каждой опечатке.