关于 reladraw
reladraw 是一种将文本描述转换为独立 SVG 图表的语言,适合需要明确控制节点位置和连线的设计者与开发者。它不自动安排布局,而是按源文件中的相对位置绘制,并报告重叠等问题。
主要功能
- 01以文本定义图表与相对位置
- 02生成无运行时依赖的 SVG
- 03支持节点、容器、样式与连线
- 04检查并报告图形重叠问题
- 05提供格式化与语法错误提示
适用场景
- 01绘制位置可预测的系统架构图
- 02为节点和连线指定明确布局
- 03检查图表中的文字或线条重叠
- 04格式化并维护 .reladraw 源文件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ reladraw/ reladraw --skill reladraw安装后在 Claude Code 中输入/reladraw确认已加载。
附带文件reference/syntax.md
详细介绍
reladraw
一种用于绘制图表的文本语言。输入源文件,输出独立 SVG,无运行时依赖。
其他图表语言都会把布局交给布局引擎,因此元素最终的位置无法从你写的内容中预测。reladraw 则反其道而行之:文件用人们会直接说出口的方式描述布局(right of api、below worker (gap: tight)、even with queue),工具会严格按此绘制。它绝不自行选择布局、不会为了腾出空间而移动方框,也不会让线绕过任何东西。
这点在这里尤其重要。你看不到生成的 SVG。使用自动布局时,你只能猜测;而使用 reladraw 时,布局就在你刚写下的句子里,如果图示可能无法表达出预期含义,工具会用文字告诉你。
检查是否已安装,以及版本是否与此技能相同
此技能介绍的是 reladraw 0.19.0。每个会话中,在首次渲染前运行一次:
reladraw --version
- **版本相同:**无需说明。
- 版本较旧,或无法识别
--version(该选项于 0.17.1 加入):此工具版本早于本页介绍的版本,因此会拒绝部分功能。请告知用户,并提供npm install -g reladraw@latest。 - **版本较新:**此技能已过时。请告知用户,并提供
npx skills add reladraw/reladraw -g以刷新技能。同时继续操作;如果错误提示中给出了替代写法,请以错误提示为准,而非本页内容。
如果尚未安装 reladraw,可以使用 npx reladraw,无需安装;运行 npm install -g reladraw 即可安装。
操作流程
- 编写一个
.reladraw文件。 - 运行
reladraw render diagram.reladraw -o diagram.svg。(-o -会将内容写入标准输出;默认输出路径为输入路径加上.svg。) - 如果失败,错误会指出行号以及应改成的内容。修正后重新运行。
- 如果成功,请阅读它输出的检查结果。每条结果占一行,说明哪些内容可能未能表达预期含义、位置在哪里,以及程度如何:
diagram.reladraw:12: warning(text-overlap): text "statements" covers the top-left corner of node resolver; the overlap is 3 units wide and 2 units tall
diagram.reladraw:9: warning(edge-node-overlap): line api -> db crosses node cache, in and out of its top
- 在源文件中逐条修正检查结果,调整元素位置或明确线条的走向,然后重新运行,直到没有检查结果。
reladraw check diagram.reladraw会输出检查结果,但不会写入 SVG。 - 交付文件前运行
reladraw format diagram.reladraw。它会根据项目的.reladraw-format(如果存在)将语句按列对齐并统一间距,但不会改变文件的绘制效果。格式化后,你编写的文件看起来就像用户项目中已有的文件一样。
没有错误且没有检查结果的文件,只表示没有任何元素相互覆盖。这并不代表图示一定清晰:请重新阅读源文件,确认布局表达了你的本意;对于大型图表,请告知用户你已检查检查结果,但没有查看渲染图。
核心理念
文件说明元素的位置,工具严格按此绘制。 间距就是你写下的距离。方框会按其放置关系定位,不会被任何东西推开。线条会在两个方框之间画成直线,除非你指定为直角或曲线,或明确列出经过的位置。任何重叠都会照样绘制,并给出报告。
因此,解决问题的办法始终是在源文件中补充说明,而不是指望工具自行处理。两个方框位于同一位置:将其中一个放到另一个旁边。线条穿过方框:用 via: 指定经过的位置。文字挤在方框旁:增大间距。
编写文件
语句从行首开始。较长的语句可续写到后续缩进行;空行或未缩进的行会结束语句。缩进不会将某个元素放入另一个元素中。// 用于开始注释,也可以写在语句末尾。
语句由一个位置主体(关键字、名称,然后是文本)以及属性和放置关系组成,顺序不限。以冒号结尾的词会开启一个属性,除此之外的内容都不会。
节点
node <name> ["<text>" [(<text settings>)]] [<placement> | <attribute>] ...
省略文本时,节点会显示其名称(node parser 会显示为“parser”)。若要有意留空节点,请写 ""。在文本中,/(两侧各有一个空格的斜杠)表示换行;TCP/IP 和 URL 会保留原样。
主体可以是 shape: rectangle | document | circle | diamond | pill | parallelogram | hexagon | trapezoid | triangle | cylinder | none(none 是普通文本,用于注释和说明;流程图形状没有几何名称时,写作 flow- 加上其含义,例如 flow-subprocess 或 flow-delay;设置放在方括号中,例如 shape: triangle (aim: up)),也可以是 icon: disk | desktop | laptop | package | cubes | cube | database,即没有边框的图片。badge: <icon> 会将图片放在文本旁,作为标签的一部分。集合之外的图片用 icon <name> 声明,并在 """ 标记之间提供 SVG;建议优先使用内置图标。
node dump "nightly dump" shape: document
node unit icon: cube right of dump
node drive "External HD" badge: disk below dump
node aside "a remark that folds" (wrap: 20) shape: none right of drive
放置
above X below X left of X right of X
above-left of X above-right of X below-left of X below-right of X
even with X top even with X bottom even with X left even with X right even with X
- 文件中恰好有一个节点未放置,即锚点。其他节点都相对于某个对象放置,可以是直接相对,也可以通过其他节点间接相对。
- 间距是精确的:在放置语句的方括号中指定
none、tight、normal(默认值)或wide,例如right of a (gap: tight);也可以指定前方的文件单位数值,例如2 right of a。普通方框的高度约为 4 个单位。 - 仅指定方向时,也会相对于目标居中。 单独写
right of a会让方框与a等高。该轴上的其他放置语句会取代居中设置:right of a even with b。 - 每个轴只能指定一次。 同一轴上的两个放置语句会被拒绝。唯一的例外是:
right of a left of b会将方框置于两者之间的空间中央,此时还必须指定高度。 - 多个目标会合并为一个区域:
below a and b会将节点置于两者下方,并在两者之间居中。 - 没有任何语句会移动方框。 两个方框都写成
right of a时,会落在同一位置,并发出提示。请将它们串联起来(b right of a、c right of b),或放入带有布局的容器中。
容器
带点的名称表示子节点:server.api 位于 server 内部,且必须先声明父节点。容器是包围其子节点的方框。可通过以下两种方式之一排列子节点:
node server "Server" layout: column (widths: match)
node server.api "API"
node server.worker "Worker"
node lab "Lab" right of server (gap: wide)
node lab.pc "PC"
node lab.nas "NAS" right of lab.pc (gap: tight)
layout: column 或 layout: row 会按书写顺序排列子节点;其方括号可设置 gap:、widths: match 和 align-children: left | center | right。不指定布局时,恰好有一个子节点未放置,其余子节点都相对于它放置。容器上的 shape: none 会隐藏方框,让这些子节点组成一个可整体放置的形状。
标题默认位于 (inside top),并沿顶部居中;(inside top, align: left) 会将标题放在左上角,(on top) 或 (outside top) 则会将标题放在边框上或边框上方。
文本
文本的所有自有属性都放在其后方的方括号中:color、size(small | normal | large)、wrap(每 n 个字符折行)和 align。
style dim text: (color: theme-muted)
node grinder "Grinder / [dim]medium-fine[/dim]"
node note "a longer remark that folds" (size: small, wrap: 30) shape: none below grinder (gap: tight)
[dim]…[/dim] 会借用某种样式的外观来显示一段文本。样式会将方括号附加到一个键上:style aside text: (size: small, color: theme-muted)。普通文本务必指定 (wrap: n),否则句子会显示为一整行,并横跨旁边的内容。
连线
edge [<name>] <from> -> <to> ["<text>" [(<placement>)]] [attributes]
<-、<-> 和 -- 也可以使用,而且每一端都可以带有标记:a <|-- b、a *--o b、a diamond--> b。from: 和 to: 用于指定书写的第一个和第二个名称所在的一侧:from: right to: left。
- 默认采用直线,在两个框之间穿过,并经过其中的所有内容;这些内容会被报告。
line: (path: square)或line: (path: curved)可根据连线两端各自的框和边来确定路径。 via:列出连线经过的位置:via: cache top表示从cache正上方经过;via: between a and b表示经过两者之间的点;via: proxy表示经过某个框的中心。这是让连线绕过某个对象的方法。- 文本位于连线中间。 使用
(at: start)、(at: 1/4)、(above edge)、(on: longest level)或(above some_box)来调整位置。文本不会移动框,因此要为带标签的连线留出空间:normal间距不足以容纳一个词,所以在带标签连线连接的框之间使用(gap: 12)或更大的间距。 line: (pattern: dashed, thickness: thick, corners: rounded, color: #d2904e);单独使用line: red表示颜色。
相对于框的某个部分
node bob "Bob the builder" (inside top) height: 7
node bob_link "bob.example.com" (size: small) inside bob bottom-center shape: none
node count "3" on bob top-right shape: circle
框的组成部分包括其 text、边 top、bottom、left、right,以及九个点(top-left、top-center、…… center …… bottom-right)。inside 会将节点放在框内并贴近该部分,outside 会将节点放在框外,on 会将节点居中放在该部分上。
样式和颜色
style store fill: theme-primary-subtle border: theme-primary badge: database
node records "Records" style: store
fill 是框的填充区域,border 是框的轮廓,line 是边的线条,文本的颜色则写在其方括号中。corners: sharp 会将框的圆角变为直角。优先使用主题颜色,它们在浅色和深色主题下都清晰可辨:theme-primary 和 theme-secondary 是强调色,-subtle 是向页面背景柔化后的强调色(用于填充框),theme-muted 是较低调的文本颜色。十六进制或 CSS 颜色在所有主题下都保持不变。
一个完整的小型文件
// A request path, left to right.
style store fill: theme-primary-subtle border: theme-primary badge: database
node browser "Browser"
node api "API server" right of browser (gap: 10)
node db "Postgres" right of api (gap: 10) style: store
node worker "Worker" below api (gap: wide)
edge browser -> api "HTTP"
edge api -> db "SQL"
edge worker -> db "writes" to: bottom line: (path: square)
node aside "The worker shares the database / but takes no HTTP traffic." (wrap: 30) shape: none below worker (gap: tight)
常见问题
- 两个框以相同方式放置。
node b right of a和node c right of a会将b和c放在同一位置。将c相对于b放置,或使用带有layout:的容器。 - 相距很近的框之间有带标签的连线。 文本位于连线上,且不会自动扩大间距,因此会覆盖框并被报告。请为放置位置设置更大的间距。
- 两个未放置的框。 只能有一个未放置。错误信息会指出这两个框。
- 重复指定同一坐标轴。
right of a even with a没问题;below a even with b对高度作了两次指定,因此会被拒绝。 - 旧语法。
level with应写作even with;节点上的gap:应放在放置语句的方括号中;边子句如below c和between a and b应写作via: c bottom和via: between a and b;contents:应写作layout: column (…);节点文本上的at:应写作(inside top, align: left)等;deck:是一种容器,应写作layout: deck cards: "Drive 1" "Drive 2"。这些写法都会被拒绝,并提示应使用的写法。 note、box或link。 它们不是语句:注释应写作node … shape: none,关键字是node和edge。- 坐标。 不存在坐标。每个位置都相对于图中的其他内容。
- 用
#写注释。 它会开启一个十六进制颜色值;注释应使用//。 - 根据其他语言猜测语法。 这里没有花括号、分号或子图。如果需要使用此处未介绍的内容,请先查看
reference/syntax.md,不要自行猜测。
参考
reference/syntax.md 是完整的语法参考,涵盖所有结构、点和区域、路径点和命名线段、线束、尺寸、辅助线、绘制顺序、检测结果、语言拒绝的写法及其原因,以及各版本的变更。需要使用本页未涵盖的结构,或错误或检测结果指出了意料之外的行为时,请查阅该文档。