ah-excalidraw-layout
Excalidraw 流程图排版引擎。输入结构化内容,输出零重叠的 Excalidraw 文件。 内嵌错题本规则,自动规避文字重叠/圆角挤压/容器撑破/箭头交叉等问题。 触发方式:/excalidraw、/画流程图、「帮我画Excalidraw」「用Excalidraw排版」「把这个做成图」 Not for: 自由绘图、手绘风格草图
معلومات المصدر
- المستودع
- ahang008/ah-excalidraw-layout
- آخر نشاط في المصدر
- ٣ أكتوبر ٢٠٢٦ في ١٢:٢٥
- لغة SKILL.md المكتشفة
- الصينية
- النجوم
- ٠
- التفرعات
- ٠
خيارات التثبيت
يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.
مراجعة ملفات المصدر
اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.
عرض SKILL.md
SKILL.md
تعليمات المصدر · معاينة للقراءة فقط- name
- ah-excalidraw-layout
- description
- Excalidraw 流程图排版引擎。输入结构化内容,输出零重叠的 Excalidraw 文件。 内嵌错题本规则,自动规避文字重叠/圆角挤压/容器撑破/箭头交叉等问题。 触发方式:/excalidraw、/画流程图、「帮我画Excalidraw」「用Excalidraw排版」「把这个做成图」 Not for: 自由绘图、手绘风格草图
# ah-excalidraw-layout:Excalidraw 流程图排版引擎
你不是画图工具,你是排版引擎。每次排版前先读完本文件的错题本规则。所有规则来自真实翻车案例。
## 错题本(MUST READ FIRST)
### 错误 1:文字与图形重叠
- 错误:多个文字元素放在同一个 `(x, y)`,或文字和矩形使用相同坐标但未绑定
- 正确:使用 `box()` 工厂函数自动绑定文字到矩形;独立文字必须确保距容器边框 >= 8px
### 错误 2:Group Frame 标签徽章与内部文字重叠
- 错误:在 group frame 边框上放置标签徽章(`y - 12`),与内部标题重叠
- 正确:取消标签徽章。Group 标题作为框内首行文字,放在 `y + PAD` 位置
### 错误 3:容器使用固定高度
- 错误:`rect(x, y, w, 350)` 硬编码高度
- 正确:`groupH = PAD + HEADER_H + 6 + items * (ITEM_H + ITEM_GAP) + PAD`
### 错误 4:内容向右无限扩展
- 错误:传记卡片放在右侧边栏,总宽度超出屏幕
- 正确:所有内容纵向排列,最大宽度 900px。需要并排时最大两列,单列 <= 400px
### 错误 5:箭头交叉混乱
- 错误:左右两组各有独立箭头直接连向下一节点
- 正确:左右两组先汇聚到"汇总节点",再从汇总节点连向下一段
### 错误 6:大圆角挤压文字
- 错误:`roundness: { type: 3 }`(大圆角)+ 文字贴近边框
- 正确:使用 `{ type: 2 }`(中小圆角),文字区相对边框内缩 >= 24px
### 错误 7:中文弯引号导致 JS 解析错误
- 错误:JS 双引号字符串内包含中文弯引号 `""`
- 正确:包含中文引号的字符串用单引号包裹,或替换为直角引号 `「」`
### 错误 8:同一卡片内不同内容区块无分隔
- 错误:传记卡片把基本信息和创作金句堆在一起
- 正确:不同区块之间加水平分隔线或 16px 以上空行
---
---
### 错误 9:不同体系的分组之间强行连线
- 错误:在两个独立体系的分组之间添加多条交叉虚线(如借势 pillars 和主角 pillars 之间 4 条 dot 连线)
- 正确:两个独立体系不需要在 pillar 级别建立关联。如果确实有关联,在更上层(汇总节点)统一交汇,不在细粒度节点之间拉线
### 错误 10:字体不统一 — 手写体与印刷体混用
- 错误:「AI 风口」「能力一」「能力二」等节点使用标准印刷字体(fontFamily: 2),与标题和正文的 Virgil 手写体(fontFamily: 1)风格割裂,像两套视觉系统拼在一起
- 发现轮次:第 7 轮(字体/边框/箭头/连线四维统一化调整)
- 正确:全图所有文字元素 `fontFamily: 1`(Virgil 手写体),生成后逐元素扫描确认无遗漏
- 自检:`grep -c '"fontFamily":2'` 返回 0
### 错误 11:边框风格不统一 — 直角细边与圆角粗边混用
- 错误:顶部节点(如三风口框)使用 `strokeWidth: 1` + 直角边框,下方色块使用 `strokeWidth: 2` + `roundness: {type: 2}`,视觉上像两套系统拼接
- 发现轮次:第 7 轮
- 正确:全图所有矩形统一 `strokeWidth: 2`、`roundness: {type: 2}`、`strokeStyle: "solid"`、`roughness: 2`
### 错误 12:箭头样式不统一 — 双线/单线/粗线/细线混用
- 错误:部分箭头是双线夹角样式,部分是普通细线箭头,部分是粗线,视觉噪音大
- 发现轮次:第 7 轮
- 正确:主流程箭头 `strokeWidth: 1.5`、辅助/汇聚箭头 `strokeWidth: 1`,全部使用 `strokeStyle: "solid"`、`endArrowhead: "arrow"`、`startArrowhead: null`,禁止双线或虚线样式
- 自检:所有 arrow 元素的 `strokeStyle === "solid"` 且 `endArrowhead === "arrow"`
### 错误 13:Mermaid 转换残留锚点 — 无意义的灰色控制点
- 错误:mermaid-to-excalidraw 转换器在多对多连接时自动插入 waypoint/anchor point(灰色圆点),这些不是有含义的内容节点,但视觉上看起来像"有东西"
- 发现轮次:第 5 轮(灰点/锚点/交叉线清理)
- 正确:直接生成 Excalidraw JSON 时(本 skill 的模式),永远不创建中间锚点。箭头路径为直接起点→终点,最多一次折弯
- 自检:不存在 type 非 arrow/rectangle/text 的中间节点
### 错误 14:文字溢出画布 — 节点宽度小于文字所需宽度
- 错误:节点设置了固定宽度,但文字行长度超出容器宽度,导致文字被截断或溢出到画布外
- 发现轮次:第 3 轮(文字溢出/分组重叠/连线交叉/宽度失控四合一)
- 正确:为每个节点计算所需宽度,公式:`nodeW = max(各文字行估算宽度) + 2 × PAD`。中文字符估算 `fontSize × 1.0 px`,英文/数字估算 `fontSize × 0.6 px`
- 自检:对每个 rect+text 组合,检查文字最长行的估算宽度 <= rect.width - 2 × PAD
### 错误 15:连接线被分组边框遮盖 — z-index 顺序导致线条不可见
- 错误:细的连接线(strokeWidth 0.8-1.2)被粗的分组边框(strokeWidth 2+)压在下面,导致关键连线在视觉上消失
- 发现轮次:第 5 轮
- 正确:连接线元素在 JSON elements 数组中的位置必须排在所有分组框矩形之后(后渲染 = 在上层)。分组框 strokeWidth 不超过连接线 strokeWidth + 1.0
### 错误 16:连接线斜向交叉 — 左节点连右目标、右节点连左目标
- 错误:「真实案例」到「能力一/能力二」的连线斜向穿插,以及「汇合」到「怎么练/核心洞察」的橙色线和紫色线交叉
- 发现轮次:第 7 轮(四维统一化调整中的连线部分)
- 正确:**左右一一对应路由** — 左侧来源 → 左侧目标,右侧来源 → 右侧目标。从左侧节点出发的箭头终点绝不出现在右侧节点上,反之亦然
- 自检:对每组并排节点,验证左侧组的箭头终点 x 坐标 < 页面中线,右侧组的箭头终点 x 坐标 > 页面中线
### 错误 17:container 绑定 ID 错位 — rect 和 text 互相引用不存在的 ID
- 错误:`box()` 工厂函数使用 `tid = rid()` 生成一个 ID,然后 `text(..., containerId=tid)` 和 `rect(..., boundElements=[tid])`——但 `text()` 和 `rect()` 内部各自通过 `rid()` 生成自己的真实 id,`tid` 既不是 text 的 id 也不是 rect 的 id。结果:rect 的 `boundElements` 指向不存在的元素,text 的 `containerId` 指向不存在的容器。渲染出来是空壳矩形,文字消失或错位。
- 发现轮次:第 8 轮(2026-07-22 三棱镜定位法 Excalidraw 生成,用户发现橙色案例框内每行前面的圆角框是空的)
- 正确:**禁止使用 containerId / boundElements 绑定**。所有 text 和 rect 用绝对坐标分别放置,text 坐标 = rect 坐标 + 内边距偏移。如必须用工厂函数,函数必须返回并正确关联两个元素的真实 id。
- 自检:`grep -c '"containerId":null'` 等于 text 元素总数;`grep -c '"boundElements"'` 返回 0
---
## 已验证模式(正例)
以下模式经 6 轮调试验证有效,生成时优先使用:
### 模式 1:游标推进布局
所有 y 坐标通过 `curY` 累进,禁止硬编码。每个 section 结束后 `curY += sectionH + GAP`。
### 模式 2:箭头汇聚路由
多来源 → 单汇总节点 → 下一段。禁止 N 条独立箭头从不同来源直接连向同一目标。
### 模式 3:左右一一对应路由(防交叉)
双列并排时,左侧列的箭头只连接左侧目标,右侧列只连接右侧目标。
### 模式 4:语义颜色体系
| 角色 | 主色 | 背景色 | 用于 |
|------|------|--------|------|
| 核心主张 | #f08c00 | #ffec99 | 标题/论点/判断力 |
| AI/技术 | #1971c2 | #d0ebff / #e7f5ff | AI 能力/工具 |
| 案例/验证 | #2f9e44 | #d3f9d8 | 真实案例 |
| 终点/结论 | #e03131 | #ffc9c9 | 最终结论 |
| 洞察/升华 | #9c36b5 | #e599f7 | 核心洞察 |
| 训练/行动 | #e8590c | #ffe8cc | 怎么练/行动 |
| 历史/辅助 | #868e96 | #f8f9fa | 历史案例 |
| 汇聚标记 | #adb5bd | #e9ecef | 箭头汇聚节点 |
### 模式 5:节点宽度自适应公式
```
估算宽度 = 中文字符数 × fontSize × 1.0 + 英文/数字字符数 × fontSize × 0.6
nodeW = max(各行估算宽度) + 2 × PAD
```
### 模式 6:双列 + 单列混合布局
- 标题/核心主张/案例/终点 → 单列全宽,居中
- 对比项/并列能力/两个分支 → 双列并排
- 汇聚节点 → 窄条居中
---
## 质量检查清单(生成后逐项自检)
| # | 检查项 | 标准 | 对应错题 |
|---|--------|------|---------|
| 1 | 字体统一 | 所有 text 元素 fontFamily: 1 | #10 |
| 2 | 边框统一 | 所有 rect 元素 strokeWidth: 2, roundness.type: 2 | #11 |
| 3 | 箭头统一 | 所有 arrow 元素 strokeStyle: solid, endArrowhead: arrow | #12 |
| 4 | 无残留锚点 | 不存在 type 非 arrow/rectangle/text 的节点 | #13 |
| 5 | 文字不溢出 | 每行估算宽度 <= 容器宽度 - 2 × PAD | #14 |
| 6 | 连接线可见 | 连接线排在分组框之后 | #15 |
| 7 | 无交叉连线 | 左源→左目标,右源→右目标 | #16 |
| 8 | 容器自适应 | group frame 高度 = 计算值,无硬编码 | #3 |
| 9 | 内边距充足 | 文字距容器边框 >= 20px | #6 |
| 10 | 圆角安全 | roundness.type <= 2,文字区内缩 >= 24px | #6 |
| 11 | 引号安全 | JS 字符串无不匹配引号 | #7 |
| 12 | 区块分隔 | 不同内容区块间有分隔线或 16px+ 间距 | #8 |
| 13 | 宽度不超限 | max(x + width) <= 960 | #4 |
| 14 | 箭头先汇聚 | 多来源 → 单汇总 → 下一段 | #5 #9 |
| 15 | 无标签重叠 | Group 标题在框内首行,不在边框上 | #2 |
| 16 | 文字不重叠 | 非绑定文字元素各有独立坐标 | #1 |
| 17 | 无 container 绑定 | 所有 text.containerId = null,rect.boundElements 不存在 | #17 |
**任一检查项未通过 → 回退修复对应元素,禁止带着缺陷交付。**
---
---
## 排版规范
### 全局常量
```
PAD = 24 // 容器内边距
HEADER_H = 22 // 分组标题高度
GAP = 20 // 段间距
ITEM_GAP = 4 // 同组条目间距
MAX_W = 880 // 最大页面宽度
```
### 布局模式
- 单列全宽(标题、金句区、总结):PAGE_W = 880
- 双列并排(对比项、并列能力、两个分支):左列 LEFT_X = 60,右列 LEFT_X + 400,单列 COL_W = 380
### 游标推进
所有 y 坐标通过 curY 逐行累进,禁止硬编码:
```
curY = 30
section1: curY += h1 + GAP
section2: curY += h2 + GAP
```
### 颜色体系
| 用途 | 主色 | 背景色 |
|---|---|---|
| 借势 | #c92a2a | #fff5f5 |
| 主角 | #6741d9 | #f8f0ff |
| 金句/交汇 | #e8590c | #fff9db |
| 总结/启示 | #2b8a3e | #ebfbee |
| 生平/辅助 | #495057 | #f8f9fa |
完整语义颜色体系见上方「已验证模式 → 模式 4」。
### 箭头规范
- 主流程箭头:strokeWidth 1.5, strokeStyle solid, endArrowhead arrow
- 汇聚辅助箭头:strokeWidth 1.0, strokeStyle solid, endArrowhead arrow
- 禁止:双线夹角样式、虚线样式、startArrowhead(见错题 #12)
- 多来源先汇聚到单节点,再统一流向下段(见错题 #5 #9 #16)
---
## 迭代记录
### v1.3.0:container 绑定 bug 修复(2026-07-22)
- 新增错题 #17:container 绑定 ID 错位
- `box()` 工厂函数的 `tid = rid()` 模式被证明在 text() 和 rect() 各自生成内部 id 时无法正确关联
- 全局规则:禁止使用 containerId / boundElements,统一用绝对坐标定位
- 质量清单新增第 17 项检查
### v1.2.0:错题本从 9 条扩至 16 条 + 新增正例模式库(2026-07-22)
**来源**:6 轮 Excalidraw 排版调试验证对话记录
对话覆盖的问题领域:
- Round 2:Mermaid 语法 → Excalidraw 转换原理
- Round 3:布局溢出四合一(文字溢出/分组重叠/连线交叉/宽度失控)
- Round 4:容器撑爆(固定高度/大圆角挤压/区块无分隔/标题贴边)
- Round 5:锚点清理(灰色 waypoint/连接线被遮盖/跨体系交叉)
- Round 7:四维统一化(字体/边框/箭头/连线风格不一致)
**新增错题 7 条(#10-#16)**:
| # | 错误 | 根因 | 解决方案 |
|---|------|------|---------|
| 10 | 字体不统一 | 部分节点使用印刷体 fontFamily:2 | 全图 fontFamily:1(Virgil 手写体) |
| 11 | 边框不统一 | 顶部用直角细边 vs 下方圆角粗边 | 统一 strokeWidth:2 + roundness.type:2 |
| 12 | 箭头不统一 | 双线/单线/粗线/细线混用 | 主流程 1.5 / 辅助 1.0 |
| 13 | Mermaid 残留锚点 | 转换器自动插入 waypoint | 直接生成 JSON 时不创建中间节点 |
| 14 | 文字溢出画布 | 节点宽度 < 文字所需宽度 | 宽度自适应公式 |
| 15 | 连接线被遮盖 | 分组框 strokeWidth 大于连接线 + z-index 在前 | 连接线排在分组框之后 |
| 16 | 连线斜向交叉 | 左源→右目标 / 右源→左目标 | 左右一一对应路由 |
**新增正例(已验证模式 6 个)**:游标推进 / 箭头汇聚 / 左右对应 / 语义颜色 / 宽度自适应 / 混合布局
**质量检查清单**:从 9 项扩至 16 项,每项标注对应错题编号
### v1.1.0:初版错题本(2026-07-22)
- 9 条错题:#1-#9(文字重叠/标签重叠/固定高度/无限右扩/箭头交叉/圆角挤压/引号错误/无分隔/跨体系连线)
- 排版规范、颜色体系、箭头规范初始版
عرض على GitHub