Files

12 KiB
Raw Permalink Blame History

Knowledge — Figma AI Plugin

Копилка находок и решений по проекту. Не наступай на грабли дважды. Пополняется по ходу разработки. Формат: проблема → решение (+ контекст/ссылка). Hermes имеет право править и дополнять этот файл самостоятельно (см. IDEA.md).

Сборка / окружение

Синхронизация билда на Matebook: архив должен сохранять build/

  • Симптом: архив на Matebook есть, но Figma продолжает показывать старую версию.
  • Причина: flat-архив, созданный через zip -j, складывает main.js и ui.js в корень. Распаковка обновляет manifest.json, но не заменяет D:\Figma Plugins\figma-ai-plugin\build\main.js и build\ui.js, на которые ссылается манифест.
  • Решение: архивировать из корня проекта с путями (tar czf /tmp/figma-ai-plugin.tar.gz --exclude=node_modules --exclude=.git .), проверить список файлов, затем распаковать в целевую папку. Для zip использовать zip -r, не zip -j. После распаковки сверить SHA-256 локальных и удалённых build/main.js, build/ui.js, manifest.json; дополнительно проверить маркер 0.1.N в удалённом build/ui.js.
  • Проверка цели: наличие архива в C:\Users\risow\Downloads не является успешным деплоем. Успешный deploy подтверждается только файлами в D:\Figma Plugins\figma-ai-plugin\build\.
  • Ссылка: IDEA.md, раздел «Рабочий флоу».

TypeScript 7.x ломает @create-figma-plugin/build

  • Симптом: TypeError: Cannot read properties of undefined (reading 'getCurrentDirectory') при build-figma-plugin.
  • Причина: build-figma-plugin ожидает ts.sys, которого нет в TS 7.
  • Решение: зафиксировать typescript на ~5.6.3 в package.json devDependencies.
  • Ссылка: package.json

tsconfig: не оверрайдить jsx на react-jsx

  • Симптом: error TS5089: Option 'jsxFactory' cannot be specified when option 'jsx' is 'react-jsx'.
  • Причина: базовый @create-figma-plugin/tsconfig уже задаёт jsx: react + jsxFactory: h.
  • Решение: в проектном tsconfig только extends + добавляем lib/types. Не трогать jsx/jsxFactory. Preact h уже импортируется в ui.tsx.
  • Ссылка: tsconfig.json

Text muted не существует — используй Muted

  • Симптом: Property 'muted' does not exist on type ... Text.
  • Решение: для приглушённого текста брать компонент <Muted> из @create-figma-plugin/ui, а не проп muted у <Text>.
  • Ссылка: src/ui.tsx

Кнопка-иконка рядом с другими IconButton — бери РОДНУЮ иконку, не инлайн-SVG

  • Симптом: иконка копирования рядом с кнопкой развернуть выглядит «другого размера»/тоньше, хотя viewBox один (24×24).
  • Причина: IconButton из @create-figma-plugin/ui оборачивает иконку в <div class="icon"> (position:absolute, БЕЗ задания размера) — размер берётся целиком из самой SVG. Родные иконки сета (IconExpand24, IconCheck24, IconCopySmall24 и т.п.) — залитые (fill="currentColor"). Моя инлайн-SVG была контурной (stroke, fill="none", stroke-width=2) — на том же 24×24 viewBox контурные lucide-иконки визуально кажутся меньше и легче, чем залитые соседки. Отсюда ощущение «разные размеры».
  • Правило (как делать правильно):
    1. Рядом с IconButton НИКОГДА не ставить текстовую <Button> с лейблом — только IconButton (пользователь прямо сказал: "Очевидно же, что там достаточно кнопки иконки").
    2. Брать иконку из родного сета @create-figma-plugin/ui (он же — адаптация lucide, залитые 24px): IconCopySmall24, IconDuplicateSmall24, IconClipboardSmall24, IconCheck24, IconExpand24 и т.д. — гарантированно совпадёт по габариту и весу с соседями.
    3. Если нужной иконки в сете нет (напр. copy/clipboard там только 16px -small), и ты делаешь инлайн-SVG — делай её залитой (fill="currentColor", без stroke), width/height=24, viewBox="0 0 24 24, чтобы вес совпал с родными. Контурные (stroke) иконки lucide рядом с залитыми соседями НЕ класть.
    4. Подтверждение действия (копирование) — переключать иконку на IconCheck24 на ~1.2 с, без текстовой подписи.
  • Ссылка: node_modules/@create-figma-plugin/ui/lib/components/icon-button/icon-button.module.css (.icon без размера), icon-24/icon-*-24.js (залитые SVG), src/ui.tsx (кнопки в тулбаре).

Плагин не запускается в Figma — нет папки build/ на Matebook

  • Симптом: плагин не открывается / Figma молча ничего не делает при Run (ошибка не всегда видна).
  • Причина: manifest.json указывает main: build/main.js и ui: build/ui.js, но в скопированной на Matebook папке папки build/ нет (старая команда синхронизации исключала её через --exclude build).
  • Решение: пересобрать на VPS (npm run build) и залить на Matebook ВЕСЬ проект вместе с build/ — исключать только node_modules и .git (они для запуска в Figma не нужны, Figma исполняет собранные build/*.js). После распаковки проверить наличие build/main.js и build/ui.js.
  • Ссылка: IDEA.md (раздел «Рабочий флоу», шаг 4), этот файл (раздел синхронизации через tar).

Рабочий флоу (VPS → Matebook → Figma)

Копия на Matebook через tar (rsync/scp с пробелами в пути падают)

  • Симптом: rsync: command not found (на Windows), scp: ambiguous target (пробел в пути).
  • Решение:
    1. На VPS: npm run build (обязательно — иначе нет папки build/)
    2. На VPS: tar czf /tmp/x.tar.gz --exclude node_modules --exclude .git . ← build/ НЕ исключать!
    3. scp /tmp/x.tar.gz risow@10.200.201.5:D:/x.tar.gz
    4. На Matebook (PowerShell): Set-Location 'D:/Figma Plugins/figma-ai-plugin'; tar xzf 'D:/x.tar.gz'
  • Ловушка: старая команда исключала --exclude build → в папке плагина на Matebook не было build/, и Figma не находила build/main.js/build/ui.js → плагин не запускался. См. gotcha «Плагин не запускается — нет build/».
  • Ссылка: IDEA.md (раздел «Рабочий флоу»)

Gitea push через токен в URL

  • Симптом: could not read Username при git push (нет credential helper).
  • Решение: remote как http://<TOKEN>:@<host>/admin/figma-ai-plugin.git. Токен должен иметь scope write:repository (без write:user создать репо нельзя — создавать через basic auth admin-ом).
  • Ссылка: IDEA.md, Gitea http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/figma-ai-plugin

ЭТАЛОН — ресайз и позиционирование (подтверждено пользователем)

Зафиксировано после коммита 47cad79. Любые правки в ui.tsx/main.ts сверять с этим. Среда замера: zoom=1, Figma UI виден (лимит окна ≈ 454×783 при full HD viewport).

Модель координат

  • reposition(x,y) / getPosition().canvasSpace — В canvas-space, отсчёт от верха шапки окна плагина (38px).
  • resize(w,h) — в ЭКРАННЫХ px. Figma КЛАМПИТ до своего лимита при видимом UI (≈454×783), при спрятанном UI (Ctrl+) — до всего viewport.
  • Перевод: wCanvas = w/zoom, hCanvasFull = (38+h)/zoom.

Периметральные ручки (8 фиолетовых div)

  • Drag (>4px) = ресайз (single-/dual-axis). Якорь фиксируется в RESIZE_START, размер считается от якоря.
  • Чистый клик (без движения):
    • Угол не в доке → телепорт в угол (dockWindow).
    • Угол в доке (край) → свободная ось = 50% viewport (DOCK_HALF), прижим в угол, выход из дока.
    • Край → телепорт в край (dockWindow).
  • Центр — ТОЛЬКО кнопкой в шапке (в периметр не входит).

Что есть «док»

  • Док = окно растянуто у КРАЯ (одна ось = 320, другая = max viewport). Углы и центр доком НЕ считаются.
  • Краевые кнопки (▬▭▏▕) пишут dockedPosRef; углы/центр — нет.

Ожидаемые значения (zoom=1, bounds 3513,-1774 · 908×872, видимый UI)

Реальный лимит: maxW≈454, maxH≈783. Растяжение срабатывает ТОЛЬКО по «своей» оси (другая клампится):

Кнопка Реал. W×H x y relX relY
◤ top-left 454×417 3513 -1774 0 0
▬ top-center 454×320 3740 -1774 227 0
◥ top-right 454×417 3867 -1774 354 0
▏ center-left 320×783 3513 -1748 0 26
⊕ center 454×417 3740 -1565 227 209
▕ center-right 320×783 4101 -1748 588 26
◣ bottom-left 454×417 3513 -1357 0 417
▭ bottom-center 454×320 3740 -1260 227 514
◢ bottom-right 454×417 3867 -1357 354 417
  • ▬ top-center: relX=227 (окно ПО ЦЕНТРУ по X), relY=0 (прижат к верху).
  • ▏ center-left: relY=26, gapT=gapB=25 (вертикально ОТЦЕНТРИРОВАНО).
  • Баг детектора: если видишь relX=0 на ▬ — окно прижалось к левому краю вместо центра (позиция считается от канона, а не реального размера). Фикс: DOCK_REFINE считает от реального window.innerWidth/Height.

Кнопки в шапке

[размер] [copy] [центр=IconDockToSide24] [развернуть/свернуть]. Сетка 3×3 из тела УДАЛЕНА.

Ресурсы (не терять)