figma-spec
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWork with a Figma spec
使用 Figma spec
You MUST always call before using any API and confirm that the target file’s plan (or the destination plan for a new file) has . does not identify which plan owns a file. If the plan is unclear, you MUST ask the user; never infer it from the file key or another plan’s access. If is false or absent for that plan, explain that Specs is unavailable and stop the workflow.
whoamifigma.spec.*specs_enabled: truewhoamispecs_enabledA native Figma spec is GitHub-Flavored Markdown (GFM) under a node. A standalone Figma spec is just one spec; a FigJam or Design file can contain several embedded specs.
SPEC_BLOCK在调用任何 API 前,必须始终调用 ,并确认目标文件的套餐(或新文件的目标套餐)具有 。 无法识别哪个套餐拥有某个文件。如果套餐不明确,必须询问用户;绝不能根据 file key 或其他套餐的访问权限进行推断。如果该套餐的 为 false 或不存在,请说明 Specs 不可用并停止工作流。
figma.spec.*whoamispecs_enabled: truewhoamispecs_enabled原生 Figma spec 是位于 节点下的 GitHub-Flavored Markdown(GFM)。独立的 Figma spec 只包含一个 spec;FigJam 或 Design 文件可以包含多个嵌入式 spec。
SPEC_BLOCKDiscover and choose the Figma spec
发现并选择 Figma spec
Resolve a supplied URL when present with and require plus . Otherwise, search the current page with , filtering for (and examine content with if needed) until you find your target. If it's not on the current page, load other pages one at a time with and repeat your query, stopping once the target is resolved.
node-idfigma.getNodeByIdAsynctype === "SPEC_BLOCK"specBlockType === "DOCUMENT"findAllWithCriteria({ types: ['SPEC_BLOCK'] })specBlockType === "DOCUMENT"figma.spec.getContentpage.loadAsync()Pass the resolved root ID to every content call. Omit only when the file is known to contain exactly one Figma spec; omission throws otherwise. Never edit ordinary canvas text nodes as a fallback.
specNodeId如果提供的 URL 中包含 ,请使用 解析该节点,并要求 且 。否则,使用 搜索当前页面,并筛选 的节点(必要时可通过 检查内容),直到找到目标。如果当前页面中不存在目标,请使用 逐个加载其他页面并重复查询,找到目标后立即停止。
node-idfigma.getNodeByIdAsynctype === "SPEC_BLOCK"specBlockType === "DOCUMENT"findAllWithCriteria({ types: ['SPEC_BLOCK'] })specBlockType === "DOCUMENT"figma.spec.getContentpage.loadAsync()每次调用内容 API 时,都要传入解析后的根节点 ID。仅当已知文件中恰好包含一个 Figma spec 时,才可以省略 ;否则省略会抛出异常。绝不能通过编辑普通画布文本节点来代替操作。
specNodeIdCreate a Figma spec on a canvas
在画布上创建 Figma spec
js
// Creates an embedded Figma spec on a Design or FigJam canvas (not a standalone Figma spec file).
const { specNodeId } = await figma.spec.createOnCanvasAsync({
title: 'Untitled spec',
content: '# Title\n\nA paragraph.\n',
})
const specNode = await figma.getNodeByIdAsync(specNodeId)
if (!specNode) throw new Error('The created Figma spec could not be resolved')
const after = await figma.spec.getContent({ specNodeId })
if (!after.markdown.includes('A paragraph.')) {
throw new Error('The new Figma spec content was not applied')
}Always pass a non-empty and a string ( is allowed). names the root; include any desired in .
titlecontent''title# H1contentjs
// Creates an embedded Figma spec on a Design or FigJam canvas (not a standalone Figma spec file).
const { specNodeId } = await figma.spec.createOnCanvasAsync({
title: 'Untitled spec',
content: '# Title\n\nA paragraph.\n',
})
const specNode = await figma.getNodeByIdAsync(specNodeId)
if (!specNode) throw new Error('The created Figma spec could not be resolved')
const after = await figma.spec.getContent({ specNodeId })
if (!after.markdown.includes('A paragraph.')) {
throw new Error('The new Figma spec content was not applied')
}始终传入非空的 和 字符串(允许使用 )。 用于命名根节点;如需 ,请将其包含在 中。
titlecontent''title# H1contentContent methods
内容方法
js
// READ — returns specNodeId, markdown, title, etc.
// The body is `markdown`, not `content`.
const before = await figma.spec.getContent({ specNodeId: chosenSpec.id })
const page = await figma.spec.getContent({
specNodeId: before.specNodeId,
offset: 100,
maxLines: 50,
})
// REPLACE — clears + recreates the document; use only for an empty first draft.
await figma.spec.setContent({
specNodeId: before.specNodeId,
content: '# Title\n\nA paragraph.\n',
})
// EDIT — find/replace; each oldText must match exactly once.
await figma.spec.editContent({
specNodeId: before.specNodeId,
edits: [{ oldText: 'First paragraph.', newText: 'Edited first paragraph.' }],
})
const after = await figma.spec.getContent({ specNodeId: before.specNodeId })
if (!after.markdown.includes('Edited first paragraph.')) {
throw new Error('The targeted Figma spec edit was not applied')
}- Use with the same
getContentbefore edits and to verify writes; DON'T rely on screenshots.specNodeId - Default to multiplayer-safe, surgical .
editContent - Use destructive only for an empty first draft or an explicit whole-document replacement.
setContent
js
// READ — returns specNodeId, markdown, title, etc.
// The body is `markdown`, not `content`.
const before = await figma.spec.getContent({ specNodeId: chosenSpec.id })
const page = await figma.spec.getContent({
specNodeId: before.specNodeId,
offset: 100,
maxLines: 50,
})
// REPLACE — clears + recreates the document; use only for an empty first draft.
await figma.spec.setContent({
specNodeId: before.specNodeId,
content: '# Title\n\nA paragraph.\n',
})
// EDIT — find/replace; each oldText must match exactly once.
await figma.spec.editContent({
specNodeId: before.specNodeId,
edits: [{ oldText: 'First paragraph.', newText: 'Edited first paragraph.' }],
})
const after = await figma.spec.getContent({ specNodeId: before.specNodeId })
if (!after.markdown.includes('Edited first paragraph.')) {
throw new Error('The targeted Figma spec edit was not applied')
}- 编辑前使用相同的 调用
specNodeId,并在写入后进行验证;不要依赖屏幕截图。getContent - 默认使用适合多人协作的精准 。
editContent - 仅在创建空白初稿或明确需要替换整个文档时,才使用破坏性的 。
setContent
Critical rules
关键规则
- requires exactly one match. Zero or multiple
editContentmatches fail without changes. Add surrounding context to make it unique.oldText - Pass Markdown as plain strings. Never encode it with /base64 or decode it with
Buffer. Base64 is only for image data URLs inside Markdown.atob() - Keep Markdown and traversal separate. handles content; node traversal exposes only document roots and embedded-canvas branches.
figma.spec.* - Preserve comment markers. Keep overlapping pairs unchanged around the same text, or the thread may detach or disappear. When in doubt copy the marked span exactly and edit around it.
[comment:<uuid>]…[/comment:<uuid>] - Use portable references. Shared Figma specs must use links such as GitHub permalinks, never machine-local paths or URLs.
localhost
- 要求仅匹配一次。 如果
editContent没有匹配项或存在多个匹配项,操作将失败且不会进行更改。请添加上下文以确保匹配项唯一。oldText - 以纯字符串形式传入 Markdown。 绝不要使用 /base64 进行编码,也不要使用
Buffer进行解码。Base64 仅可用于 Markdown 内的图片 data URL。atob() - 将 Markdown 与节点遍历分开。 负责处理内容;节点遍历仅用于公开文档根节点和嵌入式画布分支。
figma.spec.* - 保留评论标记。 保持相互重叠的 标记对及其对应文本不变,否则评论线程可能会分离或消失。如果不确定,请精确复制带标记的内容片段,并在其外部进行编辑。
[comment:<uuid>]…[/comment:<uuid>] - 使用可移植引用。 共享的 Figma spec 必须使用 GitHub 永久链接等引用,绝不能使用机器本地路径或 URL。
localhost
Style
样式
- Keep the title block first and formatted as H1, even when its text is empty. Never remove it or insert blocks before it.
- Prefer bold text in table header row.
- Use for underline, including combined formatting:
<ins>. Do not use<ins>**bold and underlined**</ins>, which only works in HTML imports.<u>
- 即使标题文本为空,也要将标题块放在最前面并设置为 H1 格式。绝不能删除标题块,也不能在其前面插入其他块。
- 表头行优先使用粗体文本。
- 使用 表示下划线,包括组合格式:
<ins>。不要使用<ins>**bold and underlined**</ins>,因为它仅适用于 HTML 导入。<u>
Images
图片
Images use GFM image syntax inside or :
setContenteditContent- embeds bytes that are decoded and uploaded.
 - is fetched server-side; disallowed hosts are rejected.

getContenthttps://<host>/spec/<fileKey>/image/<sha>?w=<width>&h=<height>在 或 中使用 GFM 图片语法:
setContenteditContent- 会嵌入经过解码并上传的字节。
 - 会在服务器端获取;不允许的主机会被拒绝。

getContenthttps://<host>/spec/<fileKey>/image/<sha>?w=<width>&h=<height>Comments
评论
Use for anchored threads. Prefer comments over leaving silent edits when you're unsure of a change.
figma.spec.comments.*js
const comment = await figma.spec.comments.create({
specNodeId: before.specNodeId,
anchorText: 'the exact rendered text to anchor to', // MUST appear exactly once
contextText: 'a longer unique substring containing anchorText', // optional; disambiguates repeats
message: 'Comment body (markdown).',
})
const { root, replies, hasMore } = await figma.spec.comments.getThread({ uuid: comment.uuid })
await figma.spec.comments.reply({ uuid: comment.uuid, message: 'A reply.' })- must match exactly once in the rendered Figma spec. Use a longer
anchorTextcontaining it to disambiguate repeated text.contextText - and
getThreadrequire the root comment UUID surfaced by areplymarker; never pass a reply UUID to[comment:<uuid>].reply
使用 创建带锚点的评论线程。如果不确定某项更改是否合适,应优先添加评论,而不是进行未说明的静默编辑。
figma.spec.comments.*js
const comment = await figma.spec.comments.create({
specNodeId: before.specNodeId,
anchorText: 'the exact rendered text to anchor to', // MUST appear exactly once
contextText: 'a longer unique substring containing anchorText', // optional; disambiguates repeats
message: 'Comment body (markdown).',
})
const { root, replies, hasMore } = await figma.spec.comments.getThread({ uuid: comment.uuid })
await figma.spec.comments.reply({ uuid: comment.uuid, message: 'A reply.' })- 必须与渲染后的 Figma spec 中的文本完全匹配且仅出现一次。使用包含
anchorText的更长anchorText来消除重复文本造成的歧义。contextText - 和
getThread需要使用由reply标记公开的根评论 UUID;绝不能将回复 UUID 传给[comment:<uuid>]。reply