(roots: SceneNode[])
| 22 | | { type: string; value: unknown } |
| 23 | |
| 24 | export function buildVisibleTree(roots: SceneNode[]): VisibleTree { |
| 25 | const depthLimit = suggestDepthLimit(roots) |
| 26 | const stats: TreeStats = { |
| 27 | totalNodes: 0, |
| 28 | maxDepth: 0, |
| 29 | depthLimit, |
| 30 | capped: false, |
| 31 | cappedNodeIds: [] |
| 32 | } |
| 33 | |
| 34 | const collectionCache = new Map<string, { name: string; modes: Map<string, string> } | null>() |
| 35 | const collectionIdByName = new Map<string, string>() |
| 36 | const warnedDuplicateCollections = new Set<string>() |
| 37 | |
| 38 | const nodes = new Map<string, NodeSnapshot>() |
| 39 | const order: string[] = [] |
| 40 | const rootIds: string[] = [] |
| 41 | |
| 42 | const getCollectionInfo = (id: string) => { |
| 43 | if (collectionCache.has(id)) return collectionCache.get(id) |
| 44 | try { |
| 45 | const collection = figma.variables.getVariableCollectionById(id) |
| 46 | if (!collection) { |
| 47 | collectionCache.set(id, null) |
| 48 | return null |
| 49 | } |
| 50 | |
| 51 | const name = collection.name || id |
| 52 | if (name) { |
| 53 | const existing = collectionIdByName.get(name) |
| 54 | if (!existing) { |
| 55 | collectionIdByName.set(name, collection.id) |
| 56 | } else if (existing !== collection.id && !warnedDuplicateCollections.has(name)) { |
| 57 | warnedDuplicateCollections.add(name) |
| 58 | logger.warn(`Duplicate variable collection name "${name}" detected.`) |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | const modes = new Map<string, string>() |
| 63 | if (Array.isArray(collection.modes)) { |
| 64 | collection.modes.forEach((mode) => { |
| 65 | modes.set(mode.modeId, mode.name || mode.modeId) |
| 66 | }) |
| 67 | } |
| 68 | |
| 69 | const info = { name, modes } |
| 70 | collectionCache.set(id, info) |
| 71 | return info |
| 72 | } catch { |
| 73 | collectionCache.set(id, null) |
| 74 | return null |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | const resolveVariableModeHint = (node: SceneNode): string | undefined => { |
| 79 | if (!('explicitVariableModes' in node)) return undefined |
| 80 | const explicit = (node as { explicitVariableModes?: Record<string, string> }) |
| 81 | .explicitVariableModes |
no test coverage detected