|
|
|
@ -60,7 +60,48 @@ async function runExport() { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
async function traverseNode(node: SceneNode, depth: number, currentFolderPath: string) { |
|
|
|
function cleanMixed(val: any): any { |
|
|
|
if (val === figma.mixed) return "MIXED"; |
|
|
|
return val; |
|
|
|
} |
|
|
|
|
|
|
|
function cleanRawProps(props: any): any { |
|
|
|
const cleaned: any = {}; |
|
|
|
for (const key of Object.keys(props)) { |
|
|
|
const val = props[key]; |
|
|
|
if (val === null || val === undefined) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (Array.isArray(val) && val.length === 0) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (key === "opacity" && val === 1) continue; |
|
|
|
if (key === "rotation" && val === 0) continue; |
|
|
|
if (key === "cornerRadius" && val === 0) continue; |
|
|
|
if (key === "topLeftRadius" && val === 0) continue; |
|
|
|
if (key === "topRightRadius" && val === 0) continue; |
|
|
|
if (key === "bottomLeftRadius" && val === 0) continue; |
|
|
|
if (key === "bottomRightRadius" && val === 0) continue; |
|
|
|
if (key === "paddingLeft" && val === 0) continue; |
|
|
|
if (key === "paddingRight" && val === 0) continue; |
|
|
|
if (key === "paddingTop" && val === 0) continue; |
|
|
|
if (key === "paddingBottom" && val === 0) continue; |
|
|
|
if (key === "itemSpacing" && val === 0) continue; |
|
|
|
if (key === "textCase" && val === "ORIGINAL") continue; |
|
|
|
if (key === "textDecoration" && val === "NONE") continue; |
|
|
|
|
|
|
|
if (key === "lineHeight" && typeof val === "object" && val.unit === "AUTO") { |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (key === "letterSpacing" && typeof val === "object" && val.value === 0) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
cleaned[key] = val; |
|
|
|
} |
|
|
|
return cleaned; |
|
|
|
} |
|
|
|
|
|
|
|
async function traverseNode(node: SceneNode, depth: number, currentFolderPath: string, rootNode: SceneNode) { |
|
|
|
allFolders.push(currentFolderPath); |
|
|
|
|
|
|
|
const indent = " ".repeat(depth); |
|
|
|
@ -70,12 +111,22 @@ async function runExport() { |
|
|
|
markdownOutput += `${indent} - Text Content: ${node.characters}\n`; |
|
|
|
} |
|
|
|
|
|
|
|
const rawProps = { |
|
|
|
let localX = node.x; |
|
|
|
let localY = node.y; |
|
|
|
if (node.id === rootNode.id) { |
|
|
|
localX = 0; |
|
|
|
localY = 0; |
|
|
|
} else if (node.absoluteBoundingBox && rootNode.absoluteBoundingBox) { |
|
|
|
localX = node.absoluteBoundingBox.x - rootNode.absoluteBoundingBox.x; |
|
|
|
localY = node.absoluteBoundingBox.y - rootNode.absoluteBoundingBox.y; |
|
|
|
} |
|
|
|
|
|
|
|
const rawProps: any = { |
|
|
|
id: node.id, |
|
|
|
width: node.width, |
|
|
|
height: node.height, |
|
|
|
x: node.x, |
|
|
|
y: node.y, |
|
|
|
x: localX, |
|
|
|
y: localY, |
|
|
|
fills: "fills" in node ? node.fills : null, |
|
|
|
strokes: "strokes" in node ? node.strokes : null, |
|
|
|
effects: "effects" in node ? node.effects : null, |
|
|
|
@ -83,7 +134,40 @@ async function runExport() { |
|
|
|
rotation: "rotation" in node ? node.rotation : null |
|
|
|
}; |
|
|
|
|
|
|
|
markdownOutput += `${indent} - Raw Properties: ${JSON.stringify(rawProps)}\n`; |
|
|
|
if (node.type === "TEXT") { |
|
|
|
rawProps.fontSize = cleanMixed(node.fontSize); |
|
|
|
rawProps.fontName = cleanMixed(node.fontName); |
|
|
|
rawProps.lineHeight = cleanMixed(node.lineHeight); |
|
|
|
rawProps.letterSpacing = cleanMixed(node.letterSpacing); |
|
|
|
rawProps.textAlignHorizontal = cleanMixed(node.textAlignHorizontal); |
|
|
|
rawProps.textAlignVertical = cleanMixed(node.textAlignVertical); |
|
|
|
rawProps.textCase = cleanMixed(node.textCase); |
|
|
|
rawProps.textDecoration = cleanMixed(node.textDecoration); |
|
|
|
} |
|
|
|
|
|
|
|
if ("layoutMode" in node) { |
|
|
|
rawProps.layoutMode = node.layoutMode; |
|
|
|
rawProps.primaryAxisAlignItems = node.primaryAxisAlignItems; |
|
|
|
rawProps.counterAxisAlignItems = node.counterAxisAlignItems; |
|
|
|
rawProps.paddingLeft = node.paddingLeft; |
|
|
|
rawProps.paddingRight = node.paddingRight; |
|
|
|
rawProps.paddingTop = node.paddingTop; |
|
|
|
rawProps.paddingBottom = node.paddingBottom; |
|
|
|
rawProps.itemSpacing = node.itemSpacing; |
|
|
|
} |
|
|
|
|
|
|
|
if ("cornerRadius" in node) { |
|
|
|
rawProps.cornerRadius = cleanMixed(node.cornerRadius); |
|
|
|
} |
|
|
|
|
|
|
|
if ("topLeftRadius" in node) { |
|
|
|
rawProps.topLeftRadius = cleanMixed(node.topLeftRadius); |
|
|
|
rawProps.topRightRadius = cleanMixed(node.topRightRadius); |
|
|
|
rawProps.bottomLeftRadius = cleanMixed(node.bottomLeftRadius); |
|
|
|
rawProps.bottomRightRadius = cleanMixed(node.bottomRightRadius); |
|
|
|
} |
|
|
|
|
|
|
|
markdownOutput += `${indent} - Raw Properties: ${JSON.stringify(cleanRawProps(rawProps))}\n`; |
|
|
|
|
|
|
|
const isTextNode = node.type === "TEXT"; |
|
|
|
|
|
|
|
@ -107,14 +191,14 @@ async function runExport() { |
|
|
|
for (const child of node.children) { |
|
|
|
const childSafeName = getSafeName(child); |
|
|
|
const childFolderPath = `${currentFolderPath}/children/${childSafeName}`; |
|
|
|
await traverseNode(child, depth + 1, childFolderPath); |
|
|
|
await traverseNode(child, depth + 1, childFolderPath, rootNode); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (const node of selection) { |
|
|
|
const safeFolderName = getSafeName(node); |
|
|
|
await traverseNode(node, 0, safeFolderName); |
|
|
|
await traverseNode(node, 0, safeFolderName, node); |
|
|
|
} |
|
|
|
|
|
|
|
figma.ui.postMessage({ |
|
|
|
|