首页
/ Understand-Anything /understand-figma 基础实现:从 Figma REST API 到 kind:"design" 知识图谱的全链路设计

Understand-Anything /understand-figma 基础实现:从 Figma REST API 到 kind:"design" 知识图谱的全链路设计

2026-09-06 09:29:23作者:裘旻烁

本文基于 Understand-Anything 仓库中的实现计划文档 2026-06-24-understand-figma-foundation.md 展开,完整梳理 /understand-figma 技能的架构决策、15 个实现任务的步骤与代码,并结合仓库中已落地的 figma 核心模块 源码与 SKILL.md 编排脚本,说明如何将一个 Figma 文件经 REST API 摄取、确定性解析、LLM 语义增强,最终合并为可在现有 dashboard 中渲染的 kind:"design" 知识图谱。读完后你将掌握该技能的完整调用链:parseFileKeyFigmaApiSourceparseDocument/extractTokensmergeDesignGraph → dashboard 渲染,以及 Token 安全、别名归一化、增量跳过等关键工程细节。

目标、架构与技术栈

计划文档开篇给出了一句话目标(Goal):

新增一个 /understand-figma 技能,通过 Figma REST API 摄取一个 Figma 文件,生成 kind:"design" 的知识图谱(pages、screens、components、component sets、instances、design tokens),并在现有 dashboard 中渲染。

整体架构分为四层,每层的职责在仓库中都有对应落点:

  1. 确定性解析层:位于 packages/core/src/figma/ 的带类型、带测试的核心模块,背后是 FigmaSource 适配器接口。对应源码 source/types.ts 中定义的 FigmaSource 接口:
export interface FigmaSource {
  fetchDocument(): Promise<FigmaDocument>;
  fetchStyles(): Promise<FigmaStyles>;
  renderImages(nodeIds: string[]): Promise<Record<string, string>>;
}
  1. LLM 语义层design-analyzer agent 只对确定性解析产出的结构做语义增强(summary、tags、保守的 related 边),不得发明结构节点。agent 定义见 design-analyzer.md
  2. 合并层mergeDesignGraph 组装出现有的 knowledge-graph.json 结构并复用 validateGraph 校验。
  3. 展示层:dashboard 增加 kind:"design" 分支与侧边栏缩略图。

文档强调的关键约束是:新增代码完全隔离,schema、持久化、校验、布局、搜索、导出全部复用既有设施。技术栈为 TypeScript(ESM、strict)、Zod、Vitest、Node ≥22 原生 fetch、React + React Flow、pnpm workspaces。

范围边界(Scope Check):该计划只覆盖 Figma 基础能力(ingestion + 结构 + 轻量设计系统模型)。路线图中的 B(flows)、C(design↔code)、D(audit)、E(planning-text)均被显式排除,各自将单独走 spec → plan 流程。计划本身可独立交付可测试的软件:运行 /understand-figma <key> 即可得到 dashboard 可渲染的合法 kind:"design" 图。

文件结构总览

计划文档给出的文件布局与仓库实际结构一致(以 understand-anything-plugin/ 为根):

Core — 新增模块 packages/core/src/figma/(仅 Node 侧,绝不从 browser-safe 子路径导出):

  • source/types.tsFigmaSource 接口 + 原始 Figma 响应类型(FigmaDocumentFigmaStyles
  • source/api-source.tsFigmaApiSource(读取 FIGMA_TOKEN,调用 GET /v1/files/:key/styles/images)+ parseFileKey(urlOrKey)
  • parse/parse-document.tsparseDocument(doc, fileKey){ nodes, edges }(page/screen/component/componentSet/instance + contains/instance_of/variant_of
  • parse/tokens.tsextractTokens(doc, styles) → token 节点 + uses_token
  • merge.tsmergeDesignGraph(manifest, analysisBatches, project) → 完整 KnowledgeGraphkind:"design"),内部执行 validateGraph
  • index.ts — Node-only 桶式导出
  • __tests__/ 下对应四套测试

Core — 修改(共享 schema/类型): packages/core/src/types.tspackages/core/src/schema.ts

Skill + agent — 新增: skills/understand-figma/SKILL.mdagents/design-analyzer.md

Dashboard — 修改: App.tsxCustomNode.tsxNodeInfo.tsx 及 dev server 的 /figma-image 端点

每个任务自包含并以一次 commit 收尾。下文按任务顺序展开。

Task 1–2:设计节点/边类型与 Zod schema 扩展

类型定义扩展(types.ts)

Task 1 在 types.ts 中做了四处修改:

  1. NodeType 追加 6 个设计类型,总量达到 27 个(5 code + 8 non-code + 3 domain + 5 knowledge + 6 design):
export type NodeType =
  | "file" | "function" | "class" | "module" | "concept"
  | "config" | "document" | "service" | "table" | "endpoint"
  | "pipeline" | "schema" | "resource"
  | "domain" | "flow" | "step"
  | "article" | "entity" | "topic" | "claim" | "source"
  | "page" | "screen" | "component" | "componentSet" | "instance" | "token";
  1. EdgeType 追加 3 个设计边(总量 38):instance_ofvariant_ofuses_token

  2. 新增 FigmaMeta 接口,这是设计节点上承载 Figma 原始信息的可选元数据:

export interface FigmaMeta {
  fileKey?: string;
  nodeId?: string;            // Figma node id, e.g. "1:23"
  figmaType?: string;         // FRAME | COMPONENT | COMPONENT_SET | INSTANCE | TEXT ...
  thumbnailUrl?: string;      // lazily filled from GET /v1/images
  dimensions?: { width: number; height: number };
  tokenKind?: "color" | "type" | "spacing" | "effect" | "grid";
  tokenValue?: string;        // e.g. "#0A84FF", "16px"
  prototypeTargets?: string[]; // roadmap B — 现在记录,边稍后生成
  componentKey?: string;       // roadmap C — 现在记录
}

注意 prototypeTargetscomponentKey 两个字段是为路线图 B(原型流程)和 C(design↔code 关联)预留的“先记录、后建边”设计——这一点在 parse-document.ts 的实现中得到印证:instance 节点会把 transitionNodeID 记入 prototypeTargets、把发布组件的 GUID 记入 componentKey,但 v1 不产出对应边。

  1. GraphNode 增加 figmaMeta? 字段,KnowledgeGraph.kind 放宽为 "codebase" | "knowledge" | "design"

验证命令:pnpm --filter @understand-anything/core build,预期 tsc 无错通过。

Zod schema 镜像扩展(schema.ts)

Task 2 在 schema.ts 中完成四件事,并配套在 schema.test.ts 中先写失败测试:

  • GraphNodeSchema.type 的枚举加入 6 个设计类型;
  • EdgeTypeSchema 追加 "instance_of", "variant_of", "uses_token"
  • KnowledgeGraphSchema.kind 放宽为 z.enum(["codebase", "knowledge", "design"]).optional(),并新增 FigmaMetaSchema(与 TS 接口逐字段对应,使用 .passthrough() 容忍扩展字段);
  • 别名归一化,这是该任务最值得注意的部分:
// NODE_TYPE_ALIASES 追加
frame: "screen",
artboard: "screen",
canvas: "page",
main_component: "component",
component_set: "componentSet",
variant_set: "componentSet",
design_token: "token",
style: "token",

// EDGE_TYPE_ALIASES 追加
instantiates: "instance_of",
variant: "variant_of",
styled_by: "uses_token",
applies_token: "uses_token",

同时删除原有的 instance_of: "exemplifies" 别名。原因:在代码知识图中 instance_of 曾被降级为 exemplifies,但设计图里“实例指向主组件”是真实语义,必须是一等边。这一点从当前 schema.ts 源码可以看到落地形式——别名表保留了 instance_of: "exemplifies" 条目,但注释说明它仅对非 design 类型的图生效,design 图中 instance_of 保持原样。测试用例明确验证了这一行为:keeps instance_of as a first-class edge (NOT rewritten to exemplifies)

计划文档附带的失败测试还覆盖了别名归一化(frame → screen)与完整 design 图的接受度。测试命令:pnpm --filter @understand-anything/core test -- schema,预期新增 3 个用例全绿且既有用例不回归。

Task 3:Figma 数据源适配器(parseFileKey + FigmaApiSource)

Task 3 建立数据接入层,源码位于 api-source.ts

parseFileKey 从用户输入的 URL 或裸 key 中提取 file key:

export function parseFileKey(urlOrKey: string): string {
  const m = urlOrKey.match(/figma\.com\/(?:file|design)\/([A-Za-z0-9]+)/);
  if (m) return m[1];
  if (/^[A-Za-z0-9]+$/.test(urlOrKey.trim())) return urlOrKey.trim();
  throw new Error(`Could not parse a Figma file key from: ${urlOrKey}`);
}

它兼容 figma.com/file/<key>figma.com/design/<key> 两种 URL 形态(后者可带 query),也接受纯字母数字裸 key;无法解析时抛出带原始输入的错误。

FigmaApiSourceFigmaSource 接口的 REST 实现,有三个值得关注的工程决策:

  1. Token 只走请求头:构造函数从 process.env.FIGMA_TOKEN 读取 token,未设置时抛出带指引的友好错误(“创建个人访问 token,然后 export FIGMA_TOKEN=<token>”);所有请求通过私有 get<T>() 方法发出,token 只出现在 X-Figma-Token 头中,不进 URL、不进日志
  2. 错误信息不泄露 token:HTTP 失败时抛出 Figma API ${path} failed: ${status} ${statusText},只含状态码与状态文本。测试用例 never leaks the token in error messages 明确断言 403 错误信息中不包含 token 字面值。
  3. 三个 API 端点fetchDocument()GET /files/${fileKey} 取完整文档树;fetchStyles()GET /files/${fileKey}/styles 取已发布样式列表;renderImages(nodeIds)GET /images/${fileKey}?ids=...&format=png&scale=1 批量渲染节点截图。

对应的原始响应类型 FigmaDocument 在仓库实现中比计划更进一步:FigmaDocument 上额外保留了 styles 映射(file-local style id → 发布样式)与 version/lastModified 字段,前者用于桥接节点样式引用(见 Task 5),后者服务于 Task 15 的增量跳过。

该任务附带 7 个测试用例:parseFileKey 的 4 种输入(/file/ URL、/design/ URL 带 query、裸 key、不可解析输入抛错)加 FigmaApiSource 的 3 个行为(缺 token 友好报错、fetch 发送正确 header、错误不泄 token)。

Task 4:确定性文档解析器(parseDocument)

parse-document.ts 是整个技能的确定性核心:把 Figma 文档树映射为 { nodes, edges } 清单,不依赖任何 LLM。其遍历策略是“浅层节点集合、深层读取”:

  • CANVAS → page:文档根节点 DOCUMENT 的直接子节点中,type === "CANVAS" 的每个都变成一个 page 节点;
  • FRAME → screen:页内 FRAME 变成 screen 节点,并把 absoluteBoundingBox 的宽高记入 figmaMeta.dimensions
  • INSTANCE → instance(深读)collectInstances 递归深入 screen 子树,凡遇到 INSTANCE 节点即创建 instance 节点,直连 screen --contains--> instance 边,并根据 componentId 连出 instance --instance_of--> component:<id> 边(weight 0.8);
  • COMPONENT / COMPONENT_SET → component / componentSetCOMPONENT_SET 的子 COMPONENT 各自建 component 节点并连 variant_of 边(weight 0.9)指向集合;
  • SECTION → 拍平:v1 中 section 的子节点直接按父页处理,不单独建节点。

节点 id 采用 <type>:<figmaId> 命名(如 screen:1:1),所有节点通过 seen 集合去重;初始 summary 为名称占位符(留给 Phase 2 的 LLM 增强),tags[type]complexity"simple"——这些占位值保证产出可以直接喂给 validateGraph

计划的测试用一个两页示例文档(Onboarding 页含 Login 帧与 SignInBtn 实例,Components 页含 Button 组件集及其两个变体)验证了七类节点 id、contains/instance_of/variant_of 边、figmaMeta 中尺寸与 fileKey,以及“每个节点 summary/tags/complexity 齐备”。

与计划相比,仓库实现有一处实质性改进:instance 的 componentKey 不再直接取 child.componentId(那只是文件内节点 id),而是查 doc.components[child.componentId]?.key全局发布 GUID,注释中说明了这一区分——componentId 本身已由 instance_of 边捕获,componentKey 才是留给路线图 C(design↔code 关联)的跨文件标识。

Task 5:设计令牌提取(extractTokens)

tokens.ts已发布样式提取 token 节点并连线,核心是两条约束:

  1. 有界集合:只有 styles.meta.styles 中已发布的样式才成为 token 节点(避免把每个节点的填充色都变成节点)。样式类型映射为:
const STYLE_KIND: Record<string, NonNullable<FigmaMeta["tokenKind"]>> = {
  FILL: "color", TEXT: "type", EFFECT: "effect", GRID: "grid",
};

token 节点 id 形如 token:color:brand-500token:<kind>:<slug(name)>)。

  1. 消费方归因:遍历文档树,凡节点带 styles(styleType → style key 的映射)且自身或祖先是一个结构节点,就为每个命中的样式发出 consumer --uses_token--> token 边(weight 0.5),并以 consumerId|tokenId 去重。

仓库实现相对计划又补了一层桥接:Figma 文档中 node.styles 的值是 file-local style id(如 "2:10"),而 token 节点以 /files/:key/styles 返回的全局发布 key 索引。实现中先经 doc.styles?.[localStyleId]?.key 桥接、桥不到再退回直接匹配;同时 walk 携带 nearestConsumerId 参数,把嵌套叶子层(TEXT/RECTANGLE 等)上的样式使用归因到最近的结构性祖先(screen/component 等),避免真实消费关系因“被着色的层本身不是图节点”而丢失。

测试用例验证:已发布 FILL 样式产生 tokenKind: "color" 的 token 节点(名称 color/brand-500),且消费它的 component:2:1 通过 uses_token 边指向该 token。

Task 6:合并为 kind:"design" 图(mergeDesignGraph)

merge.ts 负责把确定性清单(manifest)与 LLM 分析批次(analyses)合并为完整 KnowledgeGraph,共五步:

  1. 索引清单节点:按 id 克隆建索引(克隆以便安全增强);
  2. 应用 LLM 增强DesignAnalysis 只允许 id + summary? + tags? 的补丁(未知 id 静默跳过——design-analyzer 不得发明结构节点),外加保守的 related 边;
  3. 层(layers):由 contains 边构建 parent 映射,每个非 design-system 节点上溯(带环保护)到所属 page,每页一层;component/componentSet/token 三类节点统一归入 layer:design-system(名为 “Design System”);无归属的落 layer:unscoped
  4. tourDesign System 优先,随后每页一步,每步最多取 8 个节点 id;
  5. 组装 + 校验version: "1.0.0"kind: "design" 组装后执行 validateGraph。这里有一个已知的坑:既有 validateGraph 重建返回对象时不复制 kind 字段,所以合并函数在校验成功后手工把 kind: "design" 重新贴回(计划注明:未来可让 validateGraph 保留 kind,但不在本计划范围)。

计划的 4 个测试分别验证:产出合法 kind:"design" 图;页面层与 Design System 层分组正确;按 id 应用 design-analyzer 增强(summary 与 tags 被替换);tour 首步标题为 “Design System”。

Task 7–9:桶导出、扫描/合并脚本与 core 子路径

Task 7 创建 Node-only 桶文件 index.ts,只导出 parseFileKeyFigmaApiSourceparseDocumentextractTokensmergeDesignGraph 及类型,且不从 dashboard 的 browser-safe 子路径引用(该模块依赖 process.env 与 Node fetch)。仓库实现额外导出了 applyScreenThumbnails(Task 11 的缩略图逻辑抽出的共享函数)。

Task 9 在 packages/core/package.json 的 exports 中新增 ./figma 子路径,并创建两个 skill 包装脚本:

figma-scan.mjs(Phase 1 扫描)

const fileKey = parseFileKey(urlOrKey);
const source = new FigmaApiSource(fileKey); // 从 env 读 FIGMA_TOKEN;缺失时抛友好错误
const doc = await source.fetchDocument();
const styles = await source.fetchStyles().catch(() => ({ meta: { styles: [] } }));

const structural = parseDocument(doc, fileKey);
const tokens = extractTokens(doc, styles, structural.nodes, fileKey);
// ... 组装 manifest(project 元信息 + fileKey + nodes + edges)
writeFileSync(join(interDir, "scan-manifest.json"), JSON.stringify(manifest, null, 2));
// stderr 打印各类型节点计数

要点:styles 拉取失败时降级为空集合(token 是可选增强,不阻断扫描);manifest 写入 <projectRoot>/.understand-anything/intermediate/scan-manifest.json;stdout 干净、统计走 stderr。

figma-merge.mjs(Phase 3 合并):读 manifest 与全部 analysis-batch-*.json,调 mergeDesignGraph,失败则打印 result.fatalexit(1);成功则写 knowledge-graph.jsonmeta.json(含 lastAnalyzedAtgitCommitHash: ""version: "1.0.0"analyzedFiles),并打印非 auto-corrected 级别的 issue。

离线冒烟测试方法:node .../figma-scan.mjs /tmp/nope ABC123——未设 FIGMA_TOKEN 时应以友好的 “FIGMA_TOKEN is not set…” 报错退出,借此在不发起真实 API 调用的情况下验证接线。

Task 8 与 Task 10:design-analyzer agent 与 SKILL.md 编排

design-analyzer agentdesign-analyzer.md)是纯语义层。输入是约 15 个节点一组的 JSON 批次(每个含 idtypenamefigmaMeta、子节点名摘要、token 使用情况),外加全部现有节点 id 列表。任务契约:

  • summary:一两句话说明该 screen/component 是干什么用的(purpose,而非像素描述);token 则说明其角色;
  • tags:2–5 个小写标签(authentryctaempty-state 等);
  • 可选地输出保守的 related 边(仅当名称/结构明显表明同一 feature/flow);
  • 硬性规则:不得输出 6 类结构节点、不得重发结构边(contains/instance_of/variant_of/uses_token)、related 边必须用现有精确 id;
  • 输出写至 $INTERMEDIATE_DIR/analysis-batch-$BATCH_NUM.json,格式为 { "nodes": [{id, summary, tags}], "edges": [...] }

SKILL.md 编排SKILL.md)定义了完整的 Phase 0–4 流程:

  • 前置FIGMA_TOKEN 环境变量(Figma 个人访问 token)必需,缺失则停止并提示用户 export FIGMA_TOKEN=<token>;Node ≥ 22、pnpm ≥ 10。文档同时声明安全边界:token 只从环境读取、只出现在 X-Figma-Token 请求头,绝不写入图谱、meta.json、日志或中间文件;且该技能会向 api.figma.com 发起出站调用,不像 /understand 那样完全离线,需一次性告知用户。
  • Phase 0 预检:解析 URL/key 与可选 --language <lang>;确定 PROJECT_ROOT;确保 core 已构建(若 packages/core/dist/figma/index.js 缺失则 pnpm install + pnpm --filter @understand-anything/core build);建 intermediate/ 目录。
  • Phase 1 抓取与解析(确定性):运行 figma-scan.mjs,把节点计数转告用户;非零退出则转发 stderr 并停止。
  • Phase 2 分析(LLM 增强):按约 15 个节点一批、尽量按 page 分组,为每批派生一个使用 design-analyzer 定义子的 subagent;最多 5 批并发;单批失败仅告警继续(manifest 本身已是可靠基座);提供 --language 时追加语言指令。
  • Phase 3 合并:运行 figma-merge.mjs,转告统计与非 auto-corrected issue。
  • Phase 4 保存与启动:清理中间文件(保留 scan-manifest.json);汇报项目名、节点/边类型计数、layers、tour 步数与 knowledge-graph.json 路径;随后自动调用 /understand-dashboard 技能启动看板。

仓库中的 SKILL.md 在计划基础上还引入了 $UA_DIR 数据目录解析逻辑(已存在旧版 .understand-anything/ 则沿用,否则使用新版 .ua/),体现了后续演进的落地。

Task 11:屏幕缩略图预取

Figma 的 /v1/images 返回预签名图片 URL(浏览器直接加载无需鉴权),因此 v1 的策略是把 screen 的缩略图 URL 直接存进 figmaMeta.thumbnailUrl,dashboard 渲染普通 <img>。在 figma-scan.mjs 中,解析完成后仅对 screen 节点批量预取(有界集合):

// 只对 screen 预取缩略图(有界)。URL 预签名、数小时后过期——
// “生成后看”场景可接受,重跑即可刷新。
const screens = structural.nodes.filter((n) => n.type === "screen");
try {
  const images = await source.renderImages(screens.map((n) => n.figmaMeta.nodeId));
  // 把 images[nodeId] 写入对应 screen 的 figmaMeta.thumbnailUrl
} catch {
  // 缩略图是可选的——绝不让图像渲染失败拖垮整个扫描
}

仓库实现将这段逻辑抽成了独立模块 thumbnails.tsapplyScreenThumbnails(nodes, images),供正常扫描与 UP_TO_DATE 快速路径复用——因为预签名 URL 数小时后过期,重跑时必须刷新缩略图,否则 dashboard 侧边栏预览会失效。

Task 12–13:Dashboard 的设计节点渲染

由于 CustomNode.tsxtypeColors/typeTextColorsNodeInfo.tsxtypeBadgeColors 都是 Record<NodeType, ...> 全量映射,Task 1 拓宽 NodeType 后 dashboard 会编译失败,直到补齐全部 6 个设计 key——这是刻意的类型系统约束,防止遗漏。

CustomNode.tsx 复用既有主题变量(v1 不新增主题 token):

page: "var(--color-node-concept)",
screen: "var(--color-node-service)",
component: "var(--color-node-class)",
componentSet: "var(--color-node-module)",
instance: "var(--color-node-function)",
token: "var(--color-node-config)",

typeTextColorsNodeInfo.tsxtypeBadgeColors 做同构补齐(后者为带边框/背景的 badge 样式类)。

NodeInfo.tsx 另增一个 FigmaThumbnail 组件:当选中节点存在 figmaMeta.thumbnailUrl 时,在标题/类型徽标之下、summary 段落之上渲染一个圆角、loading="lazy" 的缩略图块;无 URL 时自动隐藏,因此对 codebase/knowledge 图完全无感。

验证命令均为 pnpm --filter @understand-anything/dashboard build,预期不再有 “Property 'page' is missing in type Record<NodeType,...>” 类错误。

Task 14–15:集成验证与基于文件版本的增量跳过

Task 14(完整集成验证) 确认 v1 无需改动 App.tsx/store:kind:"design" 图经既有 validateGraph + 结构化(分层)视图即可加载。验证步骤:

  1. pnpm --filter @understand-anything/core build && pnpm --filter @understand-anything/dashboard build 双包编译通过;
  2. pnpm --filter @understand-anything/core test 全量套件通过(含新增 schema、api-source、parse-document、tokens、merge 五套,无回归);
  3. 端到端冒烟(需真实 token + 小测试文件):export FIGMA_TOKEN=<token> 后依次运行 figma-scan.mjsfigma-merge.mjs,预期 .understand-anything/knowledge-graph.json"kind": "design"nodes/layers/tour 非空,dashboard 中 screen/component/token 可渲染、选中 screen 可见缩略图;
  4. Token 泄露检查grep -ri "$FIGMA_TOKEN" .understand-anything/ || echo "clean",预期输出 clean——token 绝不出现在图谱、meta 或任何中间文件中。

Task 15(增量跳过):Figma 文件响应带 version 字符串(每次编辑变化),v1 增量策略即“存版与当前版一致则跳过重分析,否则全量重分析”——这是 Figma 版 /understand 提交哈希检查的对应物。实现分四处:

  1. FigmaDocument 类型增加 version?: stringlastModified?: string(仓库实现中已存在);
  2. figma-scan.mjs 在拉取文档后读取旧 meta.jsonfigmaVersion,若 doc.version && prevVersion === doc.version && process.env.UNDERSTAND_FIGMA_FORCE !== "1" 则打印 UP_TO_DATEexit(0);manifest 同时记录 figmaVersion
  3. figma-merge.mjsmeta.json 时持久化 figmaVersion
  4. SKILL.md Phase 1 增加说明:scan 打印 UP_TO_DATE 时报 “Design graph is already up to date for this Figma file version” 并停止;需强制重建时设置 UNDERSTAND_FIGMA_FORCE=1

注意 token 检查先于版本检查,所以无 token 时离线冒烟仍以 token 错误退出,行为不变。

计划的自审、未决问题与实际落地差异

计划文档末尾的 Self-Review 声明:spec 覆盖完整(摄取/适配器、token 不泄露、浅层节点集、instance_of 提升与别名、figmaMetakind:"design"、design-analyzer、pipeline/phase、合并 + 页/DS 层 + DS 优先 tour、混合 dashboard、增量、后向兼容/共存/安全均有对应任务);无占位符——每个代码步骤都是完整代码,// ... 仅表示省略既有周边代码;类型一致性经核对(parseDocument/extractTokens/mergeDesignGraph 签名与脚本调用方一致,DesignAnalysis 与 design-analyzer 输出一致,6 个新 NodeTypetypes.tsschema.tsCustomNode.tsxNodeInfo.tsx 中一致出现)。

Open Questions(明确不在本计划内)

  • 专属 “Design” 视图模式 + legend 条目(v1 复用结构化分层视图);
  • dev-server 的 /figma-image 代理端点(永不失效的稳健缩略图,替代存储的 URL);
  • 节点内缩略图;screen 深度展开;本地 JSON 版 FigmaSource;节点级增量。

从仓库当前状态看,这些计划均已实际落地,且实现比计划文档更精细:parseDocument 引入了发布 GUID 与文件内节点 id 的区分;extractTokens 增加了 file-local style id → 全局发布 key 的桥接与最近结构祖先归因;Task 11 的缩略图逻辑被抽成可复用的 applyScreenThumbnails 模块并覆盖 UP_TO_DATE 快速路径;SKILL.md 引入了 .ua/ 数据目录兼容层。这些差异方向一致——都是在保持计划架构(确定性解析 + LLM 语义层 + 复用 validateGraph 的合并)不变的前提下补齐真实 Figma API 的细节缝隙。四套核心测试(api-source.test.tsparse-document.test.tstokens.test.tsmerge.test.ts)与 schema.test.ts 构成整条链路的可验证依据,读者可按文中命令在当前仓库复现全部验证。

登录后查看全文
热门项目推荐
相关项目推荐