8
n8n 中文网amn8n.com

从 Figma 同步 Android drawable 资源到 GitHub

中级

这是一个Engineering, Multimodal AI领域的自动化工作流,包含 14 个节点。主要使用 If, Code, Merge, HttpRequest, ManualTrigger 等节点。 通过 PR 将 Android drawable 资源从 Figma 同步至 GitHub(多密度 PNG)

前置要求
  • 可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "Wyw2TmhKVujBRhkZ",
  "meta": {
    "instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa",
    "templateCredsSetupCompleted": true
  },
  "name": "从 Figma 同步 Android drawable 资源到 GitHub",
  "tags": [],
  "nodes": [
    {
      "id": "b9ed0516-1d34-499b-85ba-7e304129b116",
      "name": "合并",
      "type": "n8n-nodes-base.merge",
      "position": [
        660,
        -280
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "8c08ddf1-e081-425c-bdb1-b46e28f48ebf",
      "name": "从 Figma 导出 URL 下载每个图像",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1320,
        -355
      ],
      "parameters": {
        "url": "={{ $json[\"url\"] }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "139ce28e-570d-443d-a347-bef3089e6e1e",
      "name": "获取 Figma URL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        880,
        -355
      ],
      "parameters": {
        "url": "=https://api.figma.com/v1/images/FIGMA_PROJECT_ID?ids={{$json[\"id\"]}}&format=png&scale={{$json[\"scale\"]}}",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Figma-Token",
              "value": "FIGMA_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "383243fc-1bd0-4968-af5e-fb6ba09e80f9",
      "name": "合并1",
      "type": "n8n-nodes-base.merge",
      "position": [
        1560,
        -220
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2,
      "alwaysOutputData": true
    },
    {
      "id": "087cce4c-2102-48f8-bee1-69468fceeec9",
      "name": "如果",
      "type": "n8n-nodes-base.if",
      "position": [
        1840,
        -220
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4f1fd504-3119-4fe0-bb8f-6af824494d41",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{$itemIndex}}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "258614f5-1704-4972-bbd4-e0bf8f4126d3",
      "name": "获取 Figma 导出 URL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        220,
        -280
      ],
      "parameters": {
        "url": "https://api.figma.com/v1/files/FIGMA_PROJECT_ID?ids=2-20347",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Figma-Token",
              "value": "FIGMA_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "417bd211-81b9-4f1c-9cdf-15b01a2d39ab",
      "name": "执行工作流",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        0,
        -280
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "03ff18dd-880b-4930-9d61-6e16d5e08078",
      "name": "查找图标和按钮",
      "type": "n8n-nodes-base.code",
      "position": [
        440,
        -380
      ],
      "parameters": {
        "jsCode": "function findIconsAndButtons(nodes, parentChain = []) {\n  let matches = [];\n\n  for (const node of nodes) {\n    const fullPath = [...parentChain, node.name].join('/');\n\n    // If current node is a match\n    if (typeof node.name === 'string' && /icon|button/i.test(node.name)) {\n      matches.push({\n        id: node.id,\n        name: node.name,\n        type: node.type,\n        fullPath: fullPath,\n        exportSettings: node.exportSettings || null,\n      });\n    }\n\n    // Recurse into children if they exist\n    if (node.children && Array.isArray(node.children)) {\n      matches.push(...findIconsAndButtons(node.children, [...parentChain, node.name]));\n    }\n  }\n\n  return matches;\n}\n\n// Start from the root document children\nconst rootNode = items[0].json.document;\nconst canvas = rootNode.children.find(child => child.type === 'CANVAS');\nconst frame = canvas.children.find(child => child.type === 'FRAME' && /forgot password/i.test(child.name));\n\nif (!frame || !frame.children) {\n  return [];\n}\n\n// Recursively collect icons and buttons\nconst results = findIconsAndButtons(frame.children);\n\nreturn results.map(node => ({\n  json: node\n}));"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "6ea0e89f-aeef-46b0-b26b-22dcace571de",
      "name": "预定义 drawable 文件夹",
      "type": "n8n-nodes-base.code",
      "position": [
        440,
        -180
      ],
      "parameters": {
        "jsCode": "return [\n  { json: { folder: 'drawable-mdpi', scale: '1' } },\n  { json: { folder: 'drawable-hdpi', scale: '1.5' } },\n  { json: { folder: 'drawable-xhdpi', scale: '2' } },\n  { json: { folder: 'drawable-xxhdpi', scale: '3' } }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "1ac6faec-8395-4f4e-bea1-82344b1a4fd8",
      "name": "过滤节点的空 URL",
      "type": "n8n-nodes-base.code",
      "position": [
        1100,
        -360
      ],
      "parameters": {
        "jsCode": "// Filter valid images and map to { nodeId, url }\nconst results = [];\n\nfor (const item of items) {\n  const images = item.json.images;\n\n  for (const nodeId in images) {\n    const url = images[nodeId];\n\n    if (url) {\n      results.push({\n        json: {\n          nodeId,\n          url\n        }\n      });\n    }\n  }\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "053297b8-705d-42b9-9531-16bf91629f93",
      "name": "编辑文件名",
      "type": "n8n-nodes-base.code",
      "position": [
        1700,
        -360
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const name = item.json.name || \"asset\";\n  const folder = item.json.folder || \"drawable-mdpi\";\n  \n  item.json.path = `app/src/main/res/${folder}/${name.toLowerCase().replace(/[^a-z0-9]/g, \"_\")}.png`;\n  item.json.commitMessage = `Add asset: ${name}.png to ${folder}`;\n  item.json.branch = \"add-assets-from-figma\";\n  item.json.repoOwner = \"REPO_OWNER\";\n  item.json.repoName = \"REPO_NAME\";\n\n  return item;\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "1678d236-4bab-4b39-a553-cd67f9cffe1a",
      "name": "准备拉取请求",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2040,
        -220
      ],
      "parameters": {
        "url": "https://api.github.com/repos/REPO_OWNER/REPO_NAME/pulls",
        "method": "POST",
        "options": {},
        "jsonBody": "{\n  \"title\": \"Add drawable assets from Figma\",\n  \"head\": \"add-assets-from-figma\",\n  \"base\": \"main\",\n  \"body\": \"This PR contains Android drawable assets exported from Figma in all resolutions.\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer GITHUB_TOKEN"
            },
            {
              "name": "Accept",
              "value": "application/vnd.github+json"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4ccbac73-ffba-45a7-a6fe-a77b8021480f",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        -460
      ],
      "parameters": {
        "width": 2280,
        "height": 440,
        "content": ""
      },
      "typeVersion": 1
    },
    {
      "id": "09523583-b2db-40d7-97df-798608513226",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        60
      ],
      "parameters": {
        "width": 2280,
        "height": 760,
        "content": "#"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "da71a6f8-28a7-467f-998e-a4fef0700dc8",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Prepare Pull Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "get figma Url",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "Edit File names",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get figma Url": {
      "main": [
        [
          {
            "node": "Filter nullable url of nodes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit File names": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute workflow": {
      "main": [
        [
          {
            "node": "Get Figma Export URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Icons & Buttons": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Figma Export URL": {
      "main": [
        [
          {
            "node": "Find Icons & Buttons",
            "type": "main",
            "index": 0
          },
          {
            "node": "Predefine drawable folders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Predefine drawable folders": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Filter nullable url of nodes": {
      "main": [
        [
          {
            "node": "Download Each Image from the Figma Export URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Each Image from the Figma Export URL": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

中级 - 工程, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
中级
节点数量14
分类2
节点类型6
难度说明

适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流

作者
WeblineIndia

WeblineIndia

@weblineindia

A Leading Software Engineering, Consulting & Outsourcing Services Company in USA & India serving Clients Globally since 1999.

外部链接
在 n8n.io 查看

分享此工作流