Аннотации (references/annotations.md)
Источник:
ds-skills/src/skills/astra-figma-doc-build/references/annotations.md— справочник скилла astra-figma-doc-build
В тексте документации нет чисел. Размеры, отступы, радиусы, цвета и типографика показываются аннотациями Figma на слоях примера в блоке «Структура». Значение Figma берёт с самого узла и показывает токен, если свойство к нему привязано. Компонент меняется — аннотации показывают новое значение, документацию переписывать не нужно.
Читатель видит аннотации в Dev Mode. Подсказку об этом даёт ds-paragraph-dev-mode
над блоком «Структура» — его текст не меняется.
Категории
figma.annotations.getAnnotationCategoriesAsync(). В файле Astra DS восемь категорий:
Спецификация | зелёный | размеры, отступы, токены, текстовые стили, заливки — по умолчанию |
Интерактивность | синий | поведение и отклик на действия |
Доступность | розовый | фокус, контраст, зона нажатия |
Контент | жёлтый | правила текста |
Рекомендации, Закон, Примечание реализации, Stark | — | скилл не ставит |
Скилл ставит только Спецификация. Новые категории не создаёт
(addAnnotationCategoryAsync не вызывать). Категории нет — берётся стандартная
Development (так в новом файле и в копии без настроек Astra), нет и её — аннотация
ставится без категории. Оба случая называются в отчёте.
Формат
node.annotations = [{
labelMarkdown: "**<Имя слоя>**",
categoryId: specId,
properties: [{ type: "padding" }, { type: "itemSpacing" }]
}];
labelMarkdown— имя слоя жирным. Назначение слоя скилл не пишет: из имени его не вывести без догадки (SKILL.md, раздел «Тексты»). Чисел в подписи нет.properties— только те, что на узле действительно заданы, иначеInvalid property … for a FRAME node.annotations— массив только для чтения: присваивать целиком.
Какие свойства на каком слое
| корень примера и фреймы с auto-layout | padding, itemSpacing; minWidth, minHeight, если заданы; cornerRadius, если не 0 |
| фрейм с заливкой или обводкой | плюс fills, strokes |
| текстовый слой | textStyleId, если стиль стоит; иначе fontSize, lineHeight; плюс fills |
| вложенный инстанс | mainComponent, width, height |
| прочее | width, height |
BOOLEAN_OPERATION и векторы внутри иконок — без аннотаций.
Рецепт
Отдельный вызов после блока «Структура» (рецепт 5.1): после setProps id внутри инстанса
могли смениться, поэтому слои ищутся заново.
// …страница…
const anatomy = await figma.getNodeByIdAsync("ANATOMY_ID");
const slot = anatomy.findOne(n => n.type === "SLOT" && n.name === "Slot Container");
const example = slot.children[0];
const cats = await figma.annotations.getAnnotationCategoriesAsync();
const spec = cats.find(c => c.label === "Спецификация");
if (!spec) return { stop: true, reason: "нет категории «Спецификация»" };
function propsFor(n) {
const p = [];
if (n.type === "TEXT") {
p.push(n.textStyleId && typeof n.textStyleId === "string" ? "textStyleId" : "fontSize");
if (n.fills && n.fills.length) p.push("fills");
return p;
}
if (n.type === "INSTANCE" && n.id !== example.id) return ["mainComponent", "width", "height"];
if (n.layoutMode && n.layoutMode !== "NONE") {
p.push("padding", "itemSpacing");
if (n.minWidth !== null) p.push("minWidth");
if (n.minHeight !== null) p.push("minHeight");
} else p.push("width", "height");
if (typeof n.cornerRadius === "number" && n.cornerRadius > 0) p.push("cornerRadius");
if (n.fills && n.fills.length) p.push("fills");
if (n.strokes && n.strokes.length) p.push("strokes");
return p;
}
// внутрь вложенных инстансов не идти: их слои описаны в документации того компонента
function insideNested(n) {
let p = n.parent;
while (p && p.id !== example.id) { if (p.type === "INSTANCE") return true; p = p.parent; }
return false;
}
const done = [], skipped = [];
const nodes = [example].concat(example.findAll(n =>
n.visible && ["FRAME", "TEXT", "INSTANCE"].includes(n.type) && !insideNested(n)));
for (const n of nodes) {
try {
n.annotations = [{ labelMarkdown: "**" + n.name + "**", categoryId: spec.id,
properties: propsFor(n).map(t => ({ type: t })) }];
done.push(n.name);
} catch (e) { skipped.push(n.name + ": " + e.message); }
}
return { done: done.length, skipped };
skipped — не ошибка сборки, а пункт отчёта: слой не принял какое-то свойство. Повторить
для него вызов с width и height.
Чего не делать
- Не дублировать. Аннотации стоят на одном примере — в «Структуре». Строки блоков свойств их не получают.
- Не писать значения в подпись. «Container — отступ 16» — ошибка: значение уже
в
properties, а в подписи оно устареет. - Линейки (
addMeasurement) доступны только в Dev Mode (figma.editorType === "dev"). В обычном режиме — не ставить и не заменять числом в тексте.