D2 圖表
D2 是一種宣告式語言:你描述形狀及其之間的連接,佈局引擎會決定所有元素的放置位置。你永遠不需要手動指定座標。這就是為什麼 D2 圖表簡短、可進行差異比對且易於日後編輯,也是為什麼大多數錯誤來自語法和佈局引擎的怪癖,而非設計本身。
此技能是 D2 v0.9.x 的完整實作知識,並已針對真實編譯器進行驗證。references/ 和 assets/templates/ 中的每個範例都能編譯通過。
工作流程
- 檢查工具。 執行
d2 --version(或scripts/d2check.sh --version)。如果缺少d2,請告知用戶並提供brew install d2或curl -fsSL https://d2lang.com/install.sh | sh -s --;請勿靜默安裝。 - 選擇圖表類型 並閱讀匹配的參考文件(下方表格)。當有適用的範本時,從
assets/templates/中的範本開始。 - 編寫
.d2檔案 到用戶想要的位置旁邊(預設:diagrams/<name>.d2)。 - 使用
scripts/d2check.sh <file.d2> [outdir] [pdf|pptx|gif]進行編譯和渲染(格式化、編譯、渲染 SVG、將 PNG 預覽放入outdir/preview/,以及任何額外格式)。切勿僅依賴d2 validate:它只解析語法。錯誤的形狀名稱、超出範圍的樣式、不受支援的佈局功能和遺失的匯入都會通過validate,但在編譯時失敗。 - 查看圖片。 在
preview/中開啟 PNG(對.png使用讀取工具)並進行判斷:重疊的標籤、糾纏的邊緣、錯誤的流向、不平衡的佈局。修正後重新渲染。一個能編譯但無法閱讀的圖表不算完成。 - 交付
.d2原始檔以及渲染後的檔案,並說明你使用了哪個佈局引擎、主題和方向,以便用戶可以自行更改。
對於快速的一次性輸出(無需建立檔案):echo 'a -> b' | d2 - out.svg。
一目瞭然的語法
direction: right # up | down | right | left(根層級;僅 TALA 允許每個容器獨立設定)
# 形狀:鍵、可選標籤、可選屬性
web: Web App {shape: rectangle} # 鍵 `web`,標籤 "Web App"
db: Postgres {shape: cylinder}
user: Customer {shape: person}
# 連接:-> <- <-> -- (始終引用 KEYS,而非標籤)
user -> web: uses
web -> db: SQL {style.stroke-dash: 3}
web -> cache: reads # 未宣告的鍵會即時建立
# 容器:點號或巢狀映射
backend: {
api -> worker: enqueue
worker -> _.db: writes # _ = 父範圍
}
web -> backend.api: HTTPS
# 樣式存在於屬性中
db.style.fill: "#e6f2ff" # 引用任何以 # 開頭的文字
(web -> db)[0].style.stroke: red # 按索引為連線設定樣式
# 重用:類別、變數、全域
classes: {
store: {shape: cylinder; style.fill: "#e6f2ff"}
}
cache.class: store
vars: {env: prod}
note: Running in ${env}
*.style.border-radius: 8
分號用於分隔同一行中的項目。# 起始註解,""" ... """ 是多行註解。鍵不區分大小寫,重複的宣告會合併(API、api 和 Api: Gateway 是一個標籤為 "Gateway" 的形狀)。
引號使用:錯誤的首要來源
未加引號的字串雖然方便,但某些字元具有特殊意義。每當標籤包含以下任何字元時,請為整個標籤加上引號("..." 或 '...'),否則編譯器可能會報錯,或者更糟的是,靜默地截斷標籤:
| 字元 | 無引號時的行為 | 範例修正 |
|---|---|---|
任何位置的 # | 行內其餘部分變成註解:a: C# language 渲染為 "C" | a: "C# language" |
開頭的 [ | 被解析為陣列:a: [JSON/HTTPS] 僅渲染 "a" | a: "[JSON/HTTPS]" |
鍵中的 . | 建立容器:svc v1.2 變成 svc v1 > 2 | "svc v1.2" |
鍵中的 & 或 [ ] | 解析錯誤(& 是全域過濾器標記) | "R&D","svc[0]" |
後面不跟著 { 的 $ | "substitutions must begin on {"(替換必須以 { 開頭) | 使用單引號:'costs $5' |
標籤開頭的 { } ` | ` | 開啟映射或區塊字串 |
用作形狀鍵的保留字(label、link、class、top、style、shape、icon、near、direction、vars ...) | "reserved keywords are prohibited in edges"(保留關鍵字禁止在邊緣中使用) | "link" -> b,或選擇不同的鍵 |
邊緣標籤內部的 -> 或 : | 實際上沒問題(a -> b: Time: 10s 可以運作) | 無需引號 |
非 ASCII 標點符號,例如 :(全形冒號) | 不會被辨識為冒號 | 使用 ASCII : ; . |
十六進制顏色必須加引號("#fff"),因為 # 會開始註解。單引號也會停用 ${...} 替換。
標籤中的換行:在加引號或未加引號的標籤中使用 \n,或使用區塊字串 |md ... | 處理富文字。
可能造成困擾的情況(請在除錯前閱讀)
- 預設佈局引擎 Dagre 無法繪製容器與其自身後代之間的連線(
a -> a.b),無法設定容器大小(width/height),也無法使用near: <object>。它會在編譯時報錯。請切換到--layout=elk(或vars.d2-config.layout-engine: elk),而不是重寫圖表。 - 保留字會進行不區分大小寫的匹配。 名為
Shape、Label、Class、Style、Link、Icon等的形狀或 UML 類別會與關鍵字衝突(reserved field shape does not accept composite)。請重新命名。 - 連接鍵,而不是標籤。 在
be: Backend之後,Backend -> x會建立一個名為 Backend 的新形狀。請使用be -> x。 - 重複的連線不會合併;兩次
a -> b會繪製兩個箭頭。請將它們標示為(a -> b)[0]、(a -> b)[1]。 d2-legend是一個變數,而不是形狀:將其放在vars: { d2-legend: { ... } }內部。頂層的d2-legend: ""只是一個名為 "d2-legend" 的普通形狀。- 時序圖:宣告的順序就是螢幕上的順序,應先宣告參與者,在群組內部只能引用存在於頂層的參與者。
- SQL 表格和 UML 類別:連接行(
orders.user_id -> users.id),並使用 ELK 或 TALA,以便邊緣能夠精確落在目標行上。 - 箭頭形狀僅在帶有箭頭的端點上渲染:
A -> B搭配source-arrowhead.shape: diamond不會在 A 處繪製任何形狀(而--則完全不繪製任何形狀)。請翻轉邊緣,使形狀位於目標端,或使用<->。 d2 fmt會重寫保留字標籤(lnk: Link變成lnk: link),而scripts/d2check.sh會就地對你的檔案執行 fmt。請引用此類標籤(lnk: "Link")。- 區塊字串
|md ... |結束於下一個|。內部的文字豎線需要使用更長的分隔符號:|md ...|或||md ... ||。 - 數值樣式範圍是強制的:
stroke-width0-15,opacity0-1,font-size8-100。text-transform接受none|uppercase|lowercase|capitalize(官方網站說是title;但編譯器拒絕它)。3d僅適用於矩形、正方形和六邊形。 - 除非要求,否則不要添加
animated: true或dark-theme-id。 動畫暗示了執行階段的資料流;深色主題會為作業系統處於深色模式的檢視者靜默地翻轉顏色。 - 形狀上的填充顏色會覆蓋主題。 優先使用主題和少數
classes;僅在顏色具有意義時才使用明確的顏色(然後添加圖例)。 - v0.9+ 版本無需瀏覽器即可渲染 PNG/PDF/PPTX/GIF。 較舊版本(<0.8)需要 Playwright/Chromium,它會在首次使用時下載。請檢查
d2 --version。 - TALA 已捆綁在 v0.9 中(
--layout=tala),但它是非確定性的:一個微小的標籤更改可能會重新調整整個佈局。如果可重複性很重要,請使用data.tala-seeds固定它。 - 多板檔案(
layers/scenarios/steps)會將 SVG 和 PNG 匯出為目錄(x/index.svg、x/layers/a.svg),並且將 PNG 渲染到相同名稱會取代 SVG 目錄。請將格式保存在單獨的資料夾中(腳本會這樣做)。對於深入探討的可交付成果,請使用 PDF(每個板一頁,可點擊的link: layers.x),並且不要手動繪製「返回」形狀:匯出器會自動添加麵包屑導航列。請參閱references/composition.md。 - 輸出檔案存在並不代表成功。 D2 可能會在發生錯誤時寫入部分渲染結果。請檢查退出碼(腳本會這樣做)。
選擇佈局、方向、主題
- 佈局引擎:
dagre(預設,快速,曲線邊)->elk(正交路由,最適合架構圖、SQL 表格、容器到容器的邊緣)->tala(對稱性,每個容器可設定direction、near: object、鎖定的top/left)。對於任何包含容器或表格的圖表,預設使用 ELK。 - 方向:對於管道流程、請求流程和寬螢幕,使用
right;對於層級結構和組織圖,使用down。為整個板選擇一個方向。 - 主題:
theme-id: 0預設;4Cool classics 和3Flagship Terrastruct 看起來現代;1neutral grey 適合樸素的文件;8對色盲友好;300/301終端機風格;303C4;200/201深色。完整表格在references/cli-and-rendering.md中。 - 將渲染設定放在檔案中,以便它們隨檔案一起傳遞:
vars: {
d2-config: {
layout-engine: elk
theme-id: 4
pad: 40
}
}
(CLI 標誌和 D2_* 環境變數會覆蓋此區塊。)
設計指導
- 每個板 3 到 12 個形狀。 超過這個數量,請使用
layers(放大檢視)、scenarios(變體)或steps(逐步建構)進行拆分,或者使用容器進行分組。 - 鍵用於命名,標籤用於人類閱讀:使用簡短的穩定鍵(
pg、auth),以及可讀的標籤(pg: PostgreSQL)。 - 邊緣標籤是動詞或協定(
reads、publishes、HTTPS),而不是句子,也不是目標的名稱。 - 使形狀與意義匹配:
cylinder儲存、queue、person、cloud外部、diamond決策、hexagon服務、document/page、package、step。不要讓所有東西都保持矩形。 - 顏色要麼編碼含義,要麼什麼都不表示。 最多約 5 個類別,透過
classes應用,並且僅在顏色攜帶了標籤未提供的資訊時才添加d2-legend。 - 每個板一個抽象層級。
- D2 用於在白板規模(最多數百個形狀)上記錄軟體和系統。它刻意沒有甘特圖、心智圖、文氏圖、桑基圖、圓餅圖/長條圖或地理地圖,並且一個物件不能存在於兩個容器中。請說明這一點,並建議使用其他工具,而不是勉強使用 D2。
參考地圖
只閱讀任務需要的部分。
| 任務 | 閱讀 |
|---|---|
| 任何語法疑問:鍵、標籤、連線、容器、字串、跳脫、註解、保留關鍵字 | references/language.md |
形狀、每個樣式鍵及其範圍、箭頭形狀、文字/Markdown/LaTeX/程式碼、圖示、near 定位、大小、主題 | references/shapes-and-styling.md |
| 時序圖、SQL 表格(ERD)、UML 類別、網格、圖例、工具提示/連結、C4 | references/diagram-types.md |
類別、變數、全域和過濾器、覆蓋和 null、匯入、suspend 模型 | references/reuse-and-globs.md |
| 圖層、情境、步驟、連結板、大型圖表的匯入、多板匯出 | references/composition.md |
CLI 標誌、佈局引擎、主題表格、匯出格式、d2-config、嵌入文件/CI、D2.js | references/cli-and-rendering.md |
| 按圖表系列(架構、流程圖、狀態、ERD、C4、組織圖...)分類的現成模式 | references/recipes.md + assets/templates/*.d2 |
| 從 Mermaid / PlantUML / Graphviz 轉換 | references/recipes.md(轉換章節) |
| 錯誤訊息或渲染錯誤的圖表 | references/troubleshooting.md |
當編譯失敗時
執行 scripts/d2check.sh file.d2。錯誤訊息格式為 file:LINE:COL: message。在 references/troubleshooting.md 中查找該訊息;常見原因包括引號問題(上文)、佈局引擎限制(切換到 ELK)、未知的形狀或超出範圍的樣式,以及區塊字串的縮排錯誤。一次修正一個錯誤並重新執行:後續的錯誤通常是第一個錯誤的後果。