关于 excalidraw-diagrams
excalidraw-diagrams 是一个使用 Python 生成可编辑 Excalidraw 图表 JSON 文件的技能。它提供通用图表、流程图和架构图接口,并支持样式配置及 PNG 导出。
主要功能
- 01生成可编辑的 .excalidraw 文件
- 02创建自动布局流程图
- 03绘制系统架构图
- 04自定义颜色、线条和文本尺寸
- 05使用 Playwright 导出 PNG
适用场景
- 01为文档绘制业务流程图
- 02展示系统组件及其连接关系
- 03制作可编辑的演示图表
- 04导出供文档使用的图像
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ robtaylor/ excalidraw-diagrams --skill excalidraw-diagrams安装后在 Claude Code 中输入/excalidraw-diagrams确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.md.gitignoreCLAUDE.mdLICENSE.github/workflows/release.ymltest-reusable-ci.ymlprompt-gallery.ymlci.ymlscripts/drive_helper.pycreate_capability_zip.pyexcalidraw_generator.pypackage-lock.jsonpackage.jsonexport_playwright.jslayout_engine.pyline_routing_validator.pytests/prompts.jsontest_diagram_types.pytest_api_skill.pytest_generator.pytest_line_routing_validator.pytest_prompt_generation.py详细介绍
Excalidraw 图表生成器
此技能使用 Python 以编程方式生成 Excalidraw 图表。不要创建 ASCII 图表,使用此工具生成专业且可编辑的图表。
输出格式:.excalidraw JSON 文件,可用于:
- 在 https://excalidraw.com 打开(拖放文件即可)
- 在 VS Code 中使用 Excalidraw 扩展编辑
- 嵌入文档
- 导出为 SVG/PNG,以便嵌入 Google Docs、演示文稿等
快速开始
方法 1:直接运行 Python 脚本(推荐)
使用生成器库编写 Python 脚本并运行:
#!/usr/bin/env python3
import sys
import os
sys.path.insert(0, os.path.expanduser("~/.claude/skills/excalidraw-diagrams/scripts"))
from excalidraw_generator import Diagram, Flowchart, ArchitectureDiagram
# Create your diagram
d = Diagram()
box1 = d.box(100, 100, "Step 1", color="blue")
box2 = d.box(300, 100, "Step 2", color="green")
d.arrow_between(box1, box2, "next")
d.save("my_diagram.excalidraw")
运行命令:
python3 /path/to/your_script.py
方法 2:内联执行 Python
python3 -c "
import sys, os
sys.path.insert(0, os.path.expanduser('~/.claude/skills/excalidraw-diagrams/scripts'))
from excalidraw_generator import Diagram
d = Diagram()
a = d.box(100, 100, 'Hello', color='blue')
b = d.box(300, 100, 'World', color='green')
d.arrow_between(a, b)
d.save('hello.excalidraw')
print('Created: hello.excalidraw')
"
API 参考
Diagram 类
所有图表的基类。
from excalidraw_generator import Diagram
d = Diagram(background="#ffffff") # white background
方法
box(x, y, label, width=150, height=60, color="blue", shape="rectangle", font_size=18)
创建带标签的形状。返回一个可用于连接的 Element。
x, y:位置(左上角)label:要显示的文本color:"blue"、"green"、"red"、"yellow"、"orange"、"violet"、"cyan"、"teal"、"gray"、"black"shape:"rectangle"、"ellipse"、"diamond"
box1 = d.box(100, 100, "Process A", color="blue")
box2 = d.box(100, 200, "Decision?", color="yellow", shape="diamond")
text_box(x, y, content, font_size=20, color="black")
创建独立文本。
d.text_box(100, 50, "System Architecture", font_size=28, color="black")
arrow_between(source, target, label=None, color="black", from_side="auto", to_side="auto")
在两个元素之间绘制箭头。
from_side、to_side:"auto"、"left"、"right"、"top"、"bottom"
d.arrow_between(box1, box2, "sends data")
d.arrow_between(box1, box3, from_side="bottom", to_side="top")
line_between(source, target, color="black")
在元素之间绘制线条(无箭头)。
save(path)
保存图表。如果未提供扩展名,则自动添加 .excalidraw。
d.save("output/my_diagram") # Creates output/my_diagram.excalidraw
配置与样式
图表生成器支持通过配置类进行广泛的自定义。
DiagramStyle - 全局外观
控制图表中所有元素的整体外观:
from excalidraw_generator import Diagram, DiagramStyle
# Create a clean, professional diagram
d = Diagram(diagram_style=DiagramStyle(
roughness=0, # 0=clean, 1=hand-drawn, 2=rough sketch
stroke_style="solid", # "solid", "dashed", "dotted"
stroke_width=2, # Line thickness (1-4)
color_scheme="corporate" # Named color scheme
))
粗糙度级别:
0- 建筑师:线条干净、精确1- 艺术家:常规手绘效果(默认)2- 漫画家:粗糙的草图效果
配色方案
使用预定义方案中的语义颜色:
# Available schemes: "default", "monochrome", "corporate", "vibrant", "earth"
d = Diagram(diagram_style=DiagramStyle(color_scheme="vibrant"))
# Get colors by role
primary = d.scheme_color("primary") # Main components
secondary = d.scheme_color("secondary") # Supporting elements
accent = d.scheme_color("accent") # Highlights
warning = d.scheme_color("warning") # Caution states
danger = d.scheme_color("danger") # Error states
neutral = d.scheme_color("neutral") # Backgrounds, users
方案颜色映射:
| 方案 | 主色 | 次色 | 强调色 | 警告色 | 危险色 |
|---|---|---|---|---|---|
| default | blue | green | violet | yellow | red |
| monochrome | black | gray | gray | gray | black |
| corporate | blue | teal | violet | orange | red |
| vibrant | violet | cyan | orange | yellow | red |
| earth | teal | green | orange | yellow | red |
FlowchartStyle - 流程图自定义
自定义流程图节点颜色和路由行为:
from excalidraw_generator import Flowchart, FlowchartStyle
fc = Flowchart(flowchart_style=FlowchartStyle(
start_color="cyan", # Start node color
end_color="red", # End node color
process_color="blue", # Process node color
decision_color="orange", # Decision diamond color
))
ArchitectureStyle - 架构图自定义
from excalidraw_generator import ArchitectureDiagram, ArchitectureStyle
arch = ArchitectureDiagram(architecture_style=ArchitectureStyle(
component_color="blue",
database_color="green",
service_color="violet",
user_color="gray",
))
BoxStyle - 文本框尺寸
控制文本框的自动尺寸调整:
from excalidraw_generator import Diagram, BoxStyle
d = Diagram(box_style=BoxStyle(
h_padding=40, # Horizontal padding (total)
v_padding=24, # Vertical padding (total)
min_width=80, # Minimum box width
min_height=40, # Minimum box height
font_size=18, # Default font size
font_family="hand" # "hand", "normal", "code"
))
Flowchart 类
专为流程图设计,支持自动定位。
from excalidraw_generator import Flowchart
fc = Flowchart(direction="vertical", spacing=80)
fc.start("Begin")
fc.process("p1", "Process Data")
fc.decision("d1", "Valid?")
fc.process("p2", "Save")
fc.end("Done")
fc.connect("__start__", "p1")
fc.connect("p1", "d1")
fc.connect("d1", "p2", label="Yes")
fc.connect("d1", "__end__", label="No")
fc.save("flowchart.excalidraw")
方法
start(label="Start")- 绿色椭圆end(label="End")- 红色椭圆process(node_id, label, color="blue")- 蓝色矩形decision(node_id, label, color="yellow")- 黄色菱形node(node_id, label, shape, color, width, height)- 通用节点connect(from_id, to_id, label=None)- 在节点之间绘制箭头position_at(x, y)- 设置下一个节点的位置
AutoLayoutFlowchart 类
用于复杂流程图,支持自动分层布局。需要 grandalf 包。
from excalidraw_generator import AutoLayoutFlowchart, DiagramStyle, FlowchartStyle, LayoutConfig
fc = AutoLayoutFlowchart(
diagram_style=DiagramStyle(roughness=0), # Clean lines
flowchart_style=FlowchartStyle(decision_color="orange"),
layout_config=LayoutConfig(
vertical_spacing=100,
horizontal_spacing=80,
)
)
# Add nodes with semantic types
fc.add_node("start", "Start", shape="ellipse", color="green", node_type="terminal")
fc.add_node("process1", "Validate Input", node_type="process")
fc.add_node("check", "Is Valid?", shape="diamond", color="yellow", node_type="decision")
fc.add_node("success", "Process Data", node_type="process")
fc.add_node("error", "Show Error", color="red", node_type="process")
fc.add_node("end", "End", shape="ellipse", color="red", node_type="terminal")
# Add edges (arrows)
fc.add_edge("start", "process1")
fc.add_edge("process1", "check")
fc.add_edge("check", "success", label="Yes")
fc.add_edge("check", "error", label="No")
fc.add_edge("success", "end")
fc.add_edge("error", "process1", label="Retry") # Back-edge auto-routes through whitespace
# Compute layout and render
result = fc.compute_layout(
two_column=True, # Split tall diagrams into columns
target_aspect_ratio=0.8, # Target width/height ratio
)
fc.save("auto_flowchart.excalidraw")
路由节点类型:
terminal- 开始/结束节点process- 标准处理步骤decision- 决策菱形(箭头从侧面引出)
方法
add_node(node_id, label, shape, color, width, height, node_type)- 添加节点add_edge(from_id, to_id, label, color)- 添加边compute_layout(start_x, start_y, max_width, max_height, routing, two_column, target_aspect_ratio, column_gap)- 自动定位节点
ArchitectureDiagram 类
用于系统架构图。
from excalidraw_generator import ArchitectureDiagram
arch = ArchitectureDiagram()
# Add components at specific positions
arch.user("user", "User", x=100, y=200)
arch.component("frontend", "React App", x=250, y=200, color="blue")
arch.service("api", "API Gateway", x=450, y=200, color="violet")
arch.database("db", "PostgreSQL", x=650, y=200, color="green")
# Connect them
arch.connect("user", "frontend", "HTTPS")
arch.connect("frontend", "api", "REST")
arch.connect("api", "db", "SQL")
arch.save("architecture.excalidraw")
方法
component(id, label, x, y, width=150, height=80, color="blue")database(id, label, x, y, color="green")- 椭圆形service(id, label, x, y, color="violet")user(id, label="User", x=100, y=100)- 灰色椭圆形connect(from_id, to_id, label=None, bidirectional=False)
颜色参考
可用颜色(描边颜色,搭配相应的浅色背景):
| 颜色 | 描边 Hex | 用途 |
|---|---|---|
blue | #1971c2 | 主要组件 |
green | #2f9e44 | 成功、数据库 |
red | #e03131 | 错误、终止状态 |
yellow | #f08c00 | 警告、决策 |
orange | #e8590c | 高亮 |
violet | #6741d9 | 服务 |
cyan | #0c8599 | 网络 |
teal | #099268 | 次要组件 |
gray | #868e96 | 用户、参与者 |
black | #1e1e1e | 文本、箭头 |
完整示例
示例 1:简单流程
import sys, os
sys.path.insert(0, os.path.expanduser("~/.claude/skills/excalidraw-diagrams/scripts"))
from excalidraw_generator import Diagram
d = Diagram()
# Title
d.text_box(200, 30, "Data Processing Pipeline", font_size=24)
# Boxes
input_box = d.box(100, 100, "Input", color="gray")
process = d.box(300, 100, "Process", color="blue")
output = d.box(500, 100, "Output", color="green")
# Arrows
d.arrow_between(input_box, process, "raw data")
d.arrow_between(process, output, "results")
d.save("pipeline.excalidraw")
示例 2:决策流程图
import sys, os
sys.path.insert(0, os.path.expanduser("~/.claude/skills/excalidraw-diagrams/scripts"))
from excalidraw_generator import Flowchart
fc = Flowchart(direction="vertical", spacing=100)
fc.start("User Request")
fc.process("auth", "Authenticate")
fc.decision("valid", "Valid Token?")
# Branch for Yes
fc.position_at(300, 340)
fc.process("proc", "Process Request")
fc.process("resp", "Return Response")
# Branch for No
fc.position_at(100, 340)
fc.process("err", "Return 401")
fc.connect("__start__", "auth")
fc.connect("auth", "valid")
fc.connect("valid", "proc", "Yes")
fc.connect("valid", "err", "No")
fc.connect("proc", "resp")
fc.save("auth_flow.excalidraw")
示例 3:微服务架构
import sys, os
sys.path.insert(0, os.path.expanduser("~/.claude/skills/excalidraw-diagrams/scripts"))
from excalidraw_generator import ArchitectureDiagram
arch = ArchitectureDiagram()
# Client layer
arch.user("client", "Client", x=400, y=50)
# Gateway
arch.service("gateway", "API Gateway", x=350, y=180, color="violet")
# Services row
arch.service("auth", "Auth Service", x=100, y=350, color="blue")
arch.service("users", "User Service", x=300, y=350, color="blue")
arch.service("orders", "Order Service", x=500, y=350, color="blue")
arch.service("notify", "Notification", x=700, y=350, color="cyan")
# Databases
arch.database("authdb", "Auth DB", x=100, y=500, color="green")
arch.database("userdb", "User DB", x=300, y=500, color="green")
arch.database("orderdb", "Order DB", x=500, y=500, color="green")
# Message queue
arch.component("queue", "Message Queue", x=600, y=450, color="orange")
# Connections
arch.connect("client", "gateway", "HTTPS")
arch.connect("gateway", "auth", "gRPC")
arch.connect("gateway", "users", "gRPC")
arch.connect("gateway", "orders", "gRPC")
arch.connect("auth", "authdb", "SQL")
arch.connect("users", "userdb", "SQL")
arch.connect("orders", "orderdb", "SQL")
arch.connect("orders", "queue", "publish")
arch.connect("queue", "notify", "subscribe")
arch.save("microservices.excalidraw")
查看输出
生成 .excalidraw 文件后:
- Excalidraw.com:访问 https://excalidraw.com 并将文件拖到画布上
- VS Code:安装 "Excalidraw" 扩展,然后打开文件
- CLI:在 macOS 上使用
open filename.excalidraw,通过默认应用打开
导出为 PNG
要将图表嵌入 Google Docs、演示文稿或其他文档,请使用 Playwright 将其导出为 PNG。
使用导出脚本
# First time setup: install dependencies
cd ~/.claude/skills/excalidraw-diagrams/scripts
npm install
npx playwright install chromium
# Export to PNG
node ~/.claude/skills/excalidraw-diagrams/scripts/export_playwright.js diagram.excalidraw output.png
工作原理
Playwright 导出脚本会:
- 在无头 Chromium 浏览器中打开 excalidraw.com
- 通过模拟拖放加载图表
- 将视图适配到内容(Shift+1)
- 以 1920x1200 分辨率截取画布
要求
- Node.js:版本 18 或更高
- Playwright:在 scripts 目录中通过
npm install安装 - Chromium:通过
npx playwright install chromium安装
提示
-
定位:使用网格系统。将形状放在 50 或 100 的倍数位置,以便对齐。
-
间距:元素之间留出 50-100px 的间距,确保箭头清晰。
-
标签:标签尽量简短(2-3 个词)。较长的描述请使用文本框。
-
颜色:相似组件使用一致的颜色(所有数据库用绿色,所有服务用蓝色)。
-
布局模式:
- 水平流程:x 增大,y 保持不变
- 垂直流程:y 增大,x 保持不变
- 网格:组合两种方式,绘制复杂图表
-
生成后:在 Excalidraw 中打开,微调位置并添加手绘元素。
Google Drive 集成
将图表直接保存到 Google Drive,以便进行云存储并通过 Excalidraw 网页版手动编辑。
快速上传
import sys, os
sys.path.insert(0, os.path.expanduser("~/.claude/skills/excalidraw-diagrams/scripts"))
from excalidraw_generator import Diagram
d = Diagram()
d.box(100, 100, "Cloud Diagram", color="blue")
# Save directly to Google Drive
result = d.save_to_drive("my_diagram.excalidraw", share_public=True)
print(f"View in Drive: {result['file']['web_view_link']}")
print(f"Edit in Excalidraw: {result['edit_url']}")
save_to_drive() 方法
save_to_drive(name=None, folder_id=None, share_public=False, local_path=None)
将图表直接保存到 Google Drive。
name:Drive 中的文件名(默认:"diagram.excalidraw")folder_id:要上传到的 Drive 文件夹 ID(默认:根目录)share_public:如果为 True,则公开文件local_path:同时将文件保存到此本地路径(可选)
返回一个 dict,包含:
file.id:Google Drive 文件 IDfile.web_view_link:在 Drive 中查看文件的链接edit_url:在 Excalidraw.com 中打开文件的链接share:共享信息(如果 share_public=True)
直接使用 drive_helper
如需更多控制,请使用 drive_helper 模块:
import sys, os
sys.path.insert(0, os.path.expanduser("~/.claude/skills/excalidraw-diagrams/scripts"))
from excalidraw_generator import Diagram
from drive_helper import upload_to_drive, share_file, search_excalidraw_files
# Create and save locally first
d = Diagram()
d.box(100, 100, "Hello")
d.save("hello.excalidraw")
# Upload to specific folder
result = upload_to_drive("hello.excalidraw", folder_id="YOUR_FOLDER_ID")
# Share with specific user
share_file(result["file"]["id"], email="[email protected]", role="writer")
# Find all excalidraw files in Drive
files = search_excalidraw_files()
DriveUploader 类
如需批量上传或整理文件夹:
from drive_helper import DriveUploader
uploader = DriveUploader(folder_id="YOUR_FOLDER_ID")
result = uploader.upload(
"diagram.excalidraw",
name="My Diagram",
share_public=True
)
手动编辑工作流
保存到 Drive 后,用户可以通过两种方式编辑图表:
-
Excalidraw.com(通过 edit_url):
- 在浏览器中打开
edit_url - Excalidraw 会从 Drive 加载文件
- 编辑并保存更改
- 在浏览器中打开
-
gdrive.excalidraw.com:
- 访问 https://gdrive.excalidraw.com
- 连接 Google Drive
- 直接打开并编辑文件
往返工作流
使用 Claude 创建 → 人工编辑 → Claude 更新:
from drive_helper import download_from_drive, update_in_drive
# Download human-edited version
download_from_drive(file_id, "updated_diagram.excalidraw")
# Make programmatic changes
d = Diagram()
# ... load and modify ...
d.save("updated_diagram.excalidraw")
# Upload changes back
update_in_drive(file_id, "updated_diagram.excalidraw")
完整工作流:将图表添加到 Google Doc
创建图表,导出为 PNG,并嵌入 Google Doc:
import sys, os, subprocess, json
sys.path.insert(0, os.path.expanduser("~/.claude/skills/excalidraw-diagrams/scripts"))
from excalidraw_generator import ArchitectureDiagram
# 1. Create the diagram
arch = ArchitectureDiagram()
arch.user("user", "User", x=50, y=150)
arch.component("frontend", "Frontend", x=200, y=130, color="blue")
arch.service("api", "API Gateway", x=400, y=130, color="violet")
arch.database("db", "Database", x=600, y=150, color="green")
arch.connect("user", "frontend", "HTTPS")
arch.connect("frontend", "api", "REST")
arch.connect("api", "db", "SQL")
# 2. Save locally and to Drive
arch.save("/tmp/architecture.excalidraw")
drive_result = arch.save_to_drive("architecture.excalidraw", share_public=True)
file_id = drive_result["file"]["id"]
edit_url = drive_result["edit_url"]
# 3. Export to PNG using Playwright
subprocess.run([
"node", os.path.expanduser("~/.claude/skills/excalidraw-diagrams/scripts/export_playwright.js"),
"/tmp/architecture.excalidraw", "/tmp/architecture.png"
])
# 4. Upload PNG to Drive and share
drive_script = os.path.expanduser("~/.claude/skills/google-docs/scripts/drive_manager.rb")
png_result = subprocess.run(
["ruby", drive_script, "upload", "--file", "/tmp/architecture.png"],
capture_output=True, text=True
)
png_data = json.loads(png_result.stdout)
png_id = png_data["file"]["id"]
# Share the PNG publicly
subprocess.run(["ruby", drive_script, "share", "--file-id", png_id, "--type", "anyone", "--role", "reader"])
png_url = f"https://drive.google.com/uc?id={png_id}&export=download"
# 5. Create Google Doc with embedded image
docs_script = os.path.expanduser("~/.claude/skills/google-docs/scripts/docs_manager.rb")
# Create document
doc_input = json.dumps({"title": "Architecture Overview", "content": "System Architecture\\n\\n"})
doc_result = subprocess.run(
["ruby", docs_script, "create"],
input=doc_input, capture_output=True, text=True
)
doc_data = json.loads(doc_result.stdout)
doc_id = doc_data["document_id"]
# Insert image (Note: SVG not supported - must use PNG)
# Width 468pt fits standard Google Doc margins; height auto-scales
img_input = json.dumps({
"document_id": doc_id,
"image_url": png_url,
"index": 25,
"width": 468 # Page width in points (fits default margins)
})
subprocess.run(["ruby", docs_script, "insert-image"], input=img_input, capture_output=True, text=True)
# Append edit link
link_input = json.dumps({"document_id": doc_id, "text": f"\\n\\nEdit diagram: {edit_url}"})
subprocess.run(["ruby", docs_script, "append"], input=link_input, capture_output=True, text=True)
print(f"Document: https://docs.google.com/document/d/{doc_id}/edit")
print(f"Edit diagram: {edit_url}")
重要提示:Google Docs 不支持 SVG 图片。嵌入时请务必导出为 PNG。
前置条件
- 必须安装 Google Docs skill(提供 OAuth 和 drive_manager.rb)
- 如果尚未完成 Google 授权,首次运行时会提示你进行授权