$npx -y skills add balabalabalading/huuuuuuho-skills --skill ardot-use强制性前置条件 — 每次调用 batch_edit 工具之前,必须先调用此技能。 未经加载此技能,绝不能直接调用 batch_edit。 当用户想要在 Ardot 设计文件中创建、更新、移动或删除节点时触发 — 例如插入框架、文本、形状、组件;将变量绑定到填充/描边; 构建屏幕、组件或设计库。当涉及 batch_edit DSL 操作时也加载 (I/U/M/D/C/G 操作符)。
| 1 | # ardot-use — Ardot batch_edit DSL 技能 |
| 2 | |
| 3 | 通过 `batch_edit` DSL 进行所有 Ardot 写操作的核心技能。提供关键规则、操作符参考、变量绑定模式、验证策略和错误恢复。 |
| 4 | |
| 5 | ## 1. 关键规则 |
| 6 | |
| 7 | **1. 每个 `batch_edit` 调用最多 25 个操作。** 将较大的工作拆分为多个调用。建议保持在 20 个或更少以留出余量。 |
| 8 | |
| 9 | **2. 绑定名称在每次 `batch_edit` 调用后过期。** 在一次调用中分配的绑定名称(例如 `btn1 = I(...)`)仅在同一调用内有效。在下一个 `batch_edit` 中,你必须使用真实节点 ID(例如 `"3:544"`)— 绝不使用先前调用的绑定名称。 |
| 10 | |
| 11 | **3. I() 中的 TEXT 节点仅支持 `fill: "#HEX"` 字符串格式。** 在 I() 中创建 TEXT 节点时不能使用 `fills: [{..., boundVariables: {...}}]`。 |
| 12 | **解决方法**:在 I() 中使用 `fill: "#HEX"` 创建 TEXT 节点,然后在后续的 `batch_edit` 调用中使用 U() 应用带有 `boundVariables` 的 `fills`。 |
| 13 | |
| 14 | **4. `updated: {}` 不代表失败。** U() 操作通常返回 `updated: {}` 而不是 `updated: {"nodeId": {...}}`。操作可能已成功 — 通过立即运行 `batch_read` 验证节点,而不是信任返回值。 |
| 15 | |
| 16 | **5. I() 必须指定父节点。** 第一个参数可以是 page、frame 的真实 ID,或同一次调用中已创建的 binding;跨页面插入时使用目标 pageId。 |
| 17 | |
| 18 | **6. M() 可以移动节点到新的父容器。** 第二个参数应是有效的父节点 ID(page 或 frame),可选第三个参数用于指定 sibling index。移动后必须读取目标父节点验证层级。 |
| 19 | |
| 20 | **7. 不支持 cornerRadius 变量绑定。** Ardot 目前不支持 `cornerRadius` 的 `boundVariables`。使用硬编码数值代替(例如 `cornerRadius: 6`)。 |
| 21 | |
| 22 | **8. 框架上的 variableModes 不可靠。** 设置 `variableModes: {"3:2": "3:3"}` 来切换颜色模式可能不会生效。使用专门的页面来表示浅色/深色模式。 |
| 23 | |
| 24 | **9. 始终 `return` 所有创建/修改的节点 ID。** 每个 `batch_edit` 响应都包含绑定名称和节点 ID。记录这些 — 在后续调用中需要它们。 |
| 25 | |
| 26 | **10. 增量构建。** 先用占位符构建骨架,然后逐个区块填充细节。每个 `batch_edit` 调用失败都是原子性的 — 文件不会被修改。 |
| 27 | |
| 28 | **11. 截图与编辑分离。** 不要在 `batch_edit` 操作中混合 `capture_screenshot` 调用。截图作为单独的验证步骤。 |
| 29 | |
| 30 | ## 2. DSL 操作符参考 |
| 31 | |
| 32 | | 操作符 | 语法 | 用途 | 关键说明 | |
| 33 | |--------|------|------|----------| |
| 34 | | `I` | `I("parentId", {type, name, ...})` | 插入新节点 | parent 可以是 page、frame 或同批次 binding;`reusable: true` 用于组件 | |
| 35 | | `U` | `U("nodeId", {props...})` | 更新现有节点 | 必须使用真实节点 ID,不能使用先前调用的绑定名称 | |
| 36 | | `M` | `M("nodeId", "parentId", index?)` | 移动节点 | 目标是新的父节点 ID,可选 index | |
| 37 | | `D` | `D("nodeId")` | 删除节点 | 删除父节点会级联到所有子节点 | |
| 38 | | `C` | `C("componentId", "parentId", {props...})` | 创建组件实例 | 在指定父节点下创建组件实例,可在 copyNodeData 中设置尺寸、位置或 descendants | |
| 39 | | `G` | `G("nodeId", "ai"\|"stock", "prompt")` | 为已有 frame/shape 应用图片填充 | 先创建承载节点,再调用 G() | |
| 40 | |
| 41 | ### I() — 插入节点 |
| 42 | |
| 43 | ```js |
| 44 | // 在 Components 页面上创建可复用按钮组件 |
| 45 | btn = I("3:1672", { |
| 46 | "type": "FRAME", |
| 47 | "name": "Button/Primary/sm", |
| 48 | "reusable": true, |
| 49 | "width": "hug_contents", |
| 50 | "height": 24, |
| 51 | "paddingLeft": 12, |
| 52 | "paddingRight": 12, |
| 53 | "paddingTop": 4, |
| 54 | "paddingBottom": 4, |
| 55 | "layout": "horizontal", |
| 56 | "cornerRadius": 6, |
| 57 | "primaryAxisAlignItems": "CENTER", |
| 58 | "fills": [{"type": "SOLID", "color": {"r": 0.91, "g": 0.44, "b": 0.29}, |
| 59 | "boundVariables": {"color": {"id": "VariableID:3:14", "type": "VARIABLE_ALIAS"}}}], |
| 60 | "children": [ |
| 61 | {"type": "TEXT", "name": "label", "characters": "Button", |
| 62 | "fontSize": 12, "fill": "#FFFFFF"} |
| 63 | ] |
| 64 | }) |
| 65 | ``` |
| 66 | |
| 67 | **关键点:** |
| 68 | - `width: "hug_contents"` — 收缩以适应内容(需要自动布局) |
| 69 | - `width: "fill_container"` — 扩展以填充父元素 |
| 70 | - `layout: "horizontal"` — 启用水平自动布局(需要 padding) |
| 71 | - TEXT 的 `fill` 在 I() 中必须是 `"#HEX"` 字符串格式 |
| 72 | - SOLID 填充的颜色值使用 0–1 范围({r, g, b}) |
| 73 | - `primaryAxisAlignItems`: `"MIN"` / `"CENTER"` / `"MAX"` |
| 74 | - `counterAxisAlignItems`: `"MIN"` / `"CENTER"` / `"MAX"` |
| 75 | |
| 76 | ### U() — 更新节点 |
| 77 | |
| 78 | ```js |
| 79 | // 将颜色变量绑定到 TEXT 节点的填充 |
| 80 | U("3:1676", { |
| 81 | "fills": [{ |
| 82 | "type": "SOLID", |
| 83 | "color": {"r": 0.61, "g": 0.59, "b": 0.56}, |
| 84 | "boundVariables": {"color": {"id": "VariableID:3:12", "type": "VARIABLE_ALIAS"}} |
| 85 | }] |
| 86 | }) |
| 87 | ``` |
| 88 | |
| 89 | ### M() — 移动节点 |
| 90 | |
| 91 | ```js |
| 92 | M("3:544", "3:1672") // 将节点 3:544 移动到 Components 页面 |
| 93 | M("3:544", "3:200", 0) // 将节点 3:544 移动到 frame 3:200 的第一个位置 |
| 94 | ``` |
| 95 | |
| 96 | - 节点在移动后保留其原始 ID |
| 97 | - 移动源组件不会破坏组件实例 |
| 98 | - 移动后用 `batch_read({parentId: "<parentId>"})` 或读取父节点 children 验证 |
| 99 | |
| 100 | ### C() — 创建组件实例 |
| 101 | |
| 102 | ```js |
| 103 | btn = C("3:544", "3:200", {x: 24, y: 200}) // 在父节点 3:200 下创建组件 3:544 的实例 |
| 104 | ``` |
| 105 | |
| 106 | - 在 copyNodeData 中可设置 x/y、width/height,或用 descendants 覆盖实例内部文本/属性 |
| 107 | |
| 108 | ## 3. 变量绑定模式 |
| 109 | |
| 110 | ### 颜色变量绑定格式(通用) |
| 111 | |
| 112 | ```json |
| 113 | "boundVariables": { |
| 114 | "color": {"id": "VariableID:<variable-id>", "type": "VARIABLE_ALIAS"} |
| 115 | } |
| 116 | ``` |
| 117 | |
| 118 | - 在 `fills[]` 中:每个填充对象上的 `boundVariables.color` |
| 119 | - 在 `strokes[]` 中:相同格式,在每个描边对象上 |
| 120 | - `cornerRadius` 绑定:不支持(见关键规则 7) |
| 121 | |
| 122 | ### TEXT 节点:两步绑定 |
| 123 | |
| 124 | 第一步 — 在 I() 中使用 `fill: "#HEX"` 创建: |
| 125 | ```js |
| 126 | I("0:1", { |
| 127 | "type": "TEXT", "characters": "Hello", |
| 128 | "fontSize": 14, "fill": "#333333" |
| 129 | }) |
| 130 | ``` |
| 131 | |
| 132 | 第二步 — 在单独的 batch_edit U() 调用中绑定变量: |
| 133 | ```js |
| 134 | U("<textNodeId>", { |
| 135 | "fills": [{ |
| 136 | "type": "SOLID", |
| 137 | "color": {"r": 0.2, "g": 0.2, "b": 0.2}, |
| 138 | "boundVariables": {"color": {"id": "VariableID:3:12", "type": "VARIABLE_ALIAS"}} |
| 139 | }] |
| 140 | }) |
| 141 | ``` |
| 142 | |
| 143 | ### 变量 ID 格式 |
| 144 | |
| 145 | ``` |
| 146 | "VariableID:3:14" — 前缀 "VariableID:" + 变量节点 ID |
| 147 | ``` |
| 148 | |
| 149 | 从 `apply_variables` 返回值或 `fetch_variables` 获取变量 ID。 |
| 150 | |
| 151 | ## 4. 验证与恢复 |
| 152 | |
| 153 | ### 验证工作流程 |
| 154 | |
| 155 | 在每批 U() 操作之后: |
| 156 | 1. 对关键节点运行 `batch_read` 以验证属性更改 |
| 157 | 2. 不要依赖 `updated: {}` — 它可能具有误导性 |
| 158 | 3. 对于视觉验证,对受影响的节点使用 `capture_screenshot` |
| 159 | 4. 如果有问题,在下一个 `batch_edit` 调用中修复 |
| 160 | |
| 161 | ### 错误恢复 |
| 162 | |
| 163 | - 每个 `batch_edit` 调用都是**原子性的** — 如果脚本失败,文件不会被更改 |
| 164 | - 出错时:读取错误消息 → 修复操作字符串 → 重试 |
| 165 | - 最常见原因:无效的节点 ID、错误的 pageId、DSL 字符串中的语法错误 |
| 166 | |
| 167 | ## 5. 预检清单 |
| 168 | |
| 169 | 在提交任何 `batch_edit` 调用之前,验证: |
| 170 | |
| 171 | - [ ] 总操作数 ≤ 25(建议 ≤ 20) |
| 172 | - [ ] 所有父引用使用此调用中的绑定 |