interface GetAnnotationsParams {
nodeId: string;
includeCategories?: boolean;
}
interface SetAnnotationParams {
nodeId: string;
labelMarkdown: string;
categoryId?: string;
}
interface SetMultipleAnnotationsParams {
nodeId: string;
annotations: Array<{
nodeId: string;
labelMarkdown: string;
categoryId?: string;
}>;
}
/**
* Get annotations on a node
*/
export async function getAnnotations(params: GetAnnotationsParams): Promise<{
nodeId: string;
annotations: Array<{
label: string;
}>;
}> {
const { nodeId } = params;
const node = await figma.getNodeByIdAsync(nodeId);
if (!node) {
throw new Error(`Node not found with ID: ${nodeId}`);
}
if (!("annotations" in node)) {
return { nodeId, annotations: [] };
}
const annotatable = node as SceneNode & {
annotations?: ReadonlyArray<Annotation>;
};
const annotations = annotatable.annotations || [];
return {
nodeId,
annotations: annotations.map((a) => ({
label: typeof a.label === "string" ? a.label : String(a.label),
})),
};
}
/**
* Set annotation on a node
*/
export async function setAnnotation(params: SetAnnotationParams): Promise<{
success: boolean;
nodeId: string;
}> {
const { nodeId, labelMarkdown } = params;
const node = await figma.getNodeByIdAsync(nodeId);
if (!node) {
throw new Error(`Node not found with ID: ${nodeId}`);
}
if (!("annotations" in node)) {
throw new Error(`Node does not support annotations: ${nodeId}`);
}
const annotatable = node as SceneNode & {
annotations: Annotation[];
};
// Create new annotation - label is a string in the Figma API
const newAnnotation: Annotation = {
label: labelMarkdown,
properties: [],
};
// Add annotation to node
annotatable.annotations = [...(annotatable.annotations || []), newAnnotation];
return {
success: true,
nodeId,
};
}
/**
* Set multiple annotations
*/
export async function setMultipleAnnotations(
params: SetMultipleAnnotationsParams,
): Promise<{
success: boolean;
appliedCount: number;
failedCount: number;
results: Array<{ nodeId: string; success: boolean; error?: string }>;
}> {
const { annotations } = params;
const results: Array<{ nodeId: string; success: boolean; error?: string }> =
[];
for (const annotation of annotations) {
try {
await setAnnotation({
nodeId: annotation.nodeId,
labelMarkdown: annotation.labelMarkdown,
categoryId: annotation.categoryId,
});
results.push({ nodeId: annotation.nodeId, success: true });
} catch (error) {
results.push({
nodeId: annotation.nodeId,
success: false,
error: error instanceof Error ? error.message : String(error),
});
}
}
return {
success: results.some((r) => r.success),
appliedCount: results.filter((r) => r.success).length,
failedCount: results.filter((r) => !r.success).length,
results,
};
}