
D2.js 演進全解析從首個公開版本到 d2-config 的能力矩陣與源碼實現【免費下載鏈接】d2D2 is a modern diagram scripting language that turns text to diagrams.項目地址: https://gitcode.com/GitHub_Trending/d2/d2本文以d2lang/d2D2.js包的官方變更記錄 d2js/js/CHANGELOG.md 為主線梳理該 JavaScript/WASM 封裝自首個公開版本以來的全部能力演進包括d2-config帶來的十余項渲染配置、自定義字體與相對導入支持、TypeScript 簽名以及D2.dispose()、并發調用修復等 Next 版本改動。讀者讀完本文將掌握 D2.js 的完整 API 面、各配置項的取值與語義并能結合 index.d.ts、src/index.js 與 d2wasm/functions.go 理解其 Worker WASM 底層運行機制。一、版本脈絡總覽一條從 可用 到 完備 的演進線CHANGELOG 記錄了 d2.js 包注意不包含主項目 d2 的變更的三個階段對應三個版本區間版本時間定位0.1.212025-01-12首個公開版本First public release0.1.222025-03-20引入d2-config、字體、相對導入與 TypeScript 簽名Next未發布—dispose()、并發修復、棄用兼容導出、體積縮減、支持 D2 0.7.1當前包版本為0.1.33見 d2js/js/package.json即 0.1.22 之后的多個補丁級發布CHANGELOG 中的 Next 條目指向的是這些后續累積改動。包名從舊命名空間terrastruct/d2過渡為d2lang/d2舊包在過渡期繼續同步發布以兼容存量用戶新裝項目應直接使用d2lang/d2。二、0.1.21首個公開版本的架構基石首個版本確立了 D2.js 的核心架構——用 Web Worker 調用 WASM 文件D2.js uses webworkers to call a WASM file。這一設計從 src/index.js 中可以清晰看到new D2()構造函數創建nextRequestId計數器與pendingRequests請求映射表并異步調用init()完成 worker 創建與 WASM 加載sendMessage(type, data)是所有 API 的統一出口為每個請求分配自增 ID存入pendingRequests再通過worker.postMessage({ id, type, data })發送worker 返回的消息中type result或error時按data.id查找對應的 Promise 并 resolve/reject見setupMessageHandler。平臺的差異化由 src/platform.browser.js 與 src/platform.node.js 提供瀏覽器端將wasm_exec.js與 worker 腳本打包進 Blob通過URL.createObjectURL創建 module 類型 WorkerWASM 二進制直接內聯無外部網絡依賴Node 端運行時按需動態import(node:worker_threads)等模塊從包目錄加載d2.wasm與worker.js。瀏覽器與 Node 共享同一套D2API這正是 README 宣稱的 Isomorphic同構特性——同一份代碼可無差別運行在兩端例如 d2js/js/examples/basic.html 展示的最小瀏覽器用例script typemodule import { D2 } from ../dist/browser/index.js; const d2 new D2(); const result await d2.compile(x - y); const svg await d2.render(result.diagram, result.renderOptions); document.getElementById(output).innerHTML svg; /script三、0.1.22d2-config與渲染能力矩陣0.1.22 是里程碑式的一次發布核心是支持d2-config——即允許在 D2 腳本內以配置塊聲明渲染選項同時讓這些選項在 JavaScript 側以結構化參數傳入。3.1 十余項新增選項及其語義按 CHANGELOG 與 index.d.ts 中的RenderOptions定義選項可劃分為四組輸出布局與幾何center是否將 SVG 在所在 viewbox 中居中默認falsepad圖形四周的內邊距像素默認100scale輸出縮放倍數例如0.5表示縮小一半。默認值會渲染出適配屏幕的 SVG顯式設為1則關閉適配target指定要渲染的 board。以layers.x.*形式渲染某一層及其全部子層傳渲染所有 scenarios/steps/layers默認只渲染根 board。多 board 輸出目前僅支持動畫 SVG因此同時必須設置animateInterval 0。主題與外觀themeID主題 ID默認0默認主題darkThemeID客戶端處于深色模式時使用的主題 IDforceAppendix是否強制為 tooltip 與鏈接追加附錄appendix默認falsesketch手繪草圖風格默認false0.1.21 已有在 0.1.22 中得到完整傳遞支持。輸出格式animateInterval單位為毫秒。設置后多個 board 會被打包進一個 SVG按該間隔依次過渡對應 Go 側的d2animate.Wrapsalt為輸出 ID 追加的鹽值字符串用于在同一 HTML 文檔中內嵌多個相同圖表時避免重復 ID 導致 HTML 非法noXMLTag從輸出 SVG 中省略?xml ...?聲明便于直接內嵌 HTML。布局引擎屬于CompileOptions而非RenderOptionslayout取值dagre或elk默認dagre。這些選項在 WASM 側的實現位于 d2wasm/functions.go 的Compile函數themeID、darkThemeID、center、pad、scale、sketch逐一被映射進d2svg.RenderOptsforceAppendix、target、animateInterval、salt、noXMLTag則寫入返回給 JS 側的RenderOptions供后續render()調用使用。layout通過LayoutResolver在dagre與elk兩個引擎間路由未知引擎會返回layout option x not recognized錯誤HTTP 風格錯誤碼 400。3.2d2-config腳本內的聲明式配置0.1.22 引入的d2-config意味著渲染選項可以在 D2 源文件內以配置塊書寫編譯后這些配置與 JS 側傳入的選項合并——compile()返回的CompileResponse.renderOptions正是渲染選項與圖表內配置合并后的結果見 index.d.ts 中CompileResponse的注釋Render options merged with configuration set in diagram。實測中腳本內配置的主題覆蓋themeOverrides會體現在返回的renderOptions中例如expect(resultOverridden.renderOptions.themeOverrides.b1).toBe(#000000)見 d2js/js/test/unit/basic.test.js。3.3 相對導入支持與 ELK 錯誤處理增強0.1.22 支持relative imports編譯請求以fs字段攜帶一份D2 文件路徑 → 內容的映射inputPath指定入口文件默認index從而支持 D2 語言的 imports 能力。在 src/index.js 中compile()對字符串輸入會包裝為{ fs: { index: input }, options }對對象輸入則透傳并合并選項。底層由 d2wasm/functions.go 的Compile將fs構造成memfs.New(...)內存文件系統再交給d2lib.Compile相對路徑引用因此在虛擬文件系統內得到解析。同時該版本改進了 ELK 布局的錯誤處理把布局失敗以明確的錯誤信息返回而非靜默失敗。3.4 自定義字體四字重 TTF 注入0.1.22 新增fontRegular、fontItalic、fontBold、fontSemiBold四個CompileOptions每個都接收一個包含.ttf文件字節的Uint8Array。若不提供則分別回退到 Source Sans Pro 的 Regular/Italic/Bold/Semibold 內置字體見 d2js/js/README.md。WASM 側的實現邏輯d2wasm/functions.goCompile四個字體字節數組先被收集只要任意一個非空就調用d2fonts.AddFontFamily(custom, ...)注冊名為custom的字族并設為compileOpts.FontFamily注冊失敗如非法字體數據會返回錯誤碼 400。這意味著開發者可以注入任意授權字體讓圖表完全貼合產品視覺體系。3.5 TypeScript 簽名首次落地0.1.22 首次提供index.d.ts類型簽名。該文件不僅是 API 的文檔還刻畫了編譯產物的完整數據結構Diagram編譯后的圖表對象包含shapes、connections、root、legend以及layers/scenarios/steps等多 board 結構Graph底層圖結構對應d2graph.Graph含edges、objects與主題信息Shape/Connection/Text等完整的形狀與連線類型Arrowhead甚至枚舉了從none、arrow到cf-one、cf-many-required的全部箭頭形態。四、Next 版本圍繞健壯性與 API 衛生的關鍵修復CHANGELOG Next 區列出了未發布版本即 0.1.23 各次補丁發布的改動每一項都能在源碼或測試中找到對應實現。4.1D2.dispose()主動釋放 Worker 資源新增的dispose()用于終止支撐當前實例的后臺 worker。在 src/index.js 的實現中冪等重復調用返回同一個disposePromise立即將disposed置為true并rejectPendingRequests(new Error(D2 instance has been disposed))拒絕所有在途請求等待ready初始化完成后調用worker.terminate()。這解決了此前困擾 Node 用戶的進程無法退出問題——CHANGELOG 原文強調調用時機當實例不再需要時調用以便 Node 進程可以退出、瀏覽器 worker 資源被釋放。所有單元測試d2js/js/test/unit/basic.test.js與 CJS/ESM 集成測試d2js/js/test/integration/cjs.test.cjs、d2js/js/test/integration/esm.test.mjs均在末尾調用await d2.dispose()。此外sendMessage在disposed后調用會直接拋錯防止在已釋放實例上誤操作。4.2 并發調用共享實例修復Next 修復了concurrent calls sharing a D2 instance問題。從源碼看請求-響應的關聯依賴pendingRequests映射表與自增id每個sendMessage都會先await this.ready再登記請求。此前的競態隱患在于初始化完成前發起多個調用可能因ready未就緒而丟失響應當前實現通過先等待 ready、再登記 ID、后 postMessage的順序保證了多個并發調用可以正確路由到各自的 Promise是pendingRequests設計得以并發安全的前提。4.3 棄用舊兼容導出getELKGraph與getObjOrderraw WASM 層的d2.getELKGraph與d2.getObjOrder兼容導出被標記棄用它們仍可調用一個發布周期且每個導出只輸出一次遷移警告。棄用原因在 d2wasm/functions.go 的注釋中寫得很明確getELKGraph的替代方案是d2.compile配合options.layout: elk——ELK 布局已內置進 D2 本體無需在 JS 側預處理 ELK 圖getObjOrder的替代方案是 Go 集成中的d2oracle.GetObjOrder。兩者均通過sync.Once保證警告僅觸發一次。這是典型的 API 衛生策略給出明確的遷移路徑同時避免對存量調用方的破壞。4.4 其余修復與支持Unicode 字符后的補全修復LSP 補全GetCompletions改用 UTF-16 定位d2lsp.GetCompletionItemsUTF16修正了中文等多字節字符后的光標偏移問題TypeScript 簽名修復基于用戶反饋持續修正index.d.ts中與運行時行為不符的聲明theme-overrides 不生效修復腳本內themeOverrides此前未能正確傳導至渲染修復后通過RenderOptions攜帶單元測試以b1: #000000斷言驗證ELK 布局中 grids 修復網格grid圖形在 ELK 引擎下的布局問題顯著縮減 bundle 體積減少內聯資源與冗余代碼降低瀏覽器加載成本支持 D2 0.7.1WASM 內核隨主項目升級version()可返回對應版本號。五、完整實戰一條數據從 D2 源碼到 SVG 的調用鏈綜合 READMEd2js/js/README.md與源碼一次完整的 D2.js 調用可以分為五步import { D2 } from d2lang/d2; // Node 與瀏覽器寫法一致 const d2 new D2(); // 1. 創建實例異步初始化 worker WASM // 2. 編譯字符串輸入走默認入口 index const result await d2.compile(x - y, { layout: dagre, sketch: true, themeID: 0, }); // 3. 渲染compile 返回的 renderOptions 已合并腳本內 d2-config const svg await d2.render(result.diagram, result.renderOptions); // 4. 釋放資源Next 版本引入 await d2.dispose();多文件導入場景傳入fs映射與inputPath例如const fs { project.d2: a: import, import.d2: x: {shape: circle}, }; const result await d2.compile({ fs, inputPath: project.d2, options: { sketch: true }, }); const svg await d2.render(result.diagram, result.renderOptions);這條鏈路在 Worker 內的對應處理見 src/worker.browser.jscompile消息把數據JSON.stringify后交給 WASM 導出返回的 JSON 若含error字段則拋錯否則將response.data回傳主線程render消息額外做了一次 base64 解碼SVG 以字節流返回。WASM 側的編譯入口則是 d2wasm/functions.go 的Compile它依次完成校驗fs與inputPath→ 構造內存文件系統與文本測量器 → 注冊自定義字體 → 解析layout→ 調用d2lib.Compile→ 格式化源碼回寫fs→ 組裝CompileResponse含diagram、graph、合并后的renderOptions。六、遷移與工程實踐建議從舊導出遷移若你曾直接調用 raw WASM 的getELKGraph/getObjOrder請改走compile()的標準路徑——layout: elk已內置、對象順序可通過返回的graph推導。棄用警告只會出現一次遷移完成后即可在后續版本移除這些調用。始終 dispose在單頁應用中圖表生命周期結束時調用await d2.dispose()避免 worker 泄漏與 Node 進程掛起重復調用是安全的。充分利用 d2-config把themeID、pad、scale、animateInterval、noXMLTag等寫在 D2 腳本配置塊中JS 側只負責業務輸入圖表語義保持自包含。多圖共存用 salt同一 HTML 中內嵌多個相同圖表時為每個實例傳入不同的salt防止 SVG 中重復 ID 破壞 HTML 結構與樣式定位。多 board 動畫的前提target指向多個 board 時務必同時設置animateInterval 0否則編譯會以錯誤拒絕源碼中明確校驗!noChildren animateInterval 0時報錯。七、結語從 0.1.21 的 Worker WASM 最小可用架構到 0.1.22 的d2-config選項矩陣、自定義字體與相對導入再到 Next 階段的dispose()、并發安全與 API 衛生清理D2.js 的演進史本身就是一份如何做好一個 WASM 封裝層的范本。它的 API 設計始終遵循同一原則Node 與瀏覽器同構、腳本與 JS 雙入口配置、所有復雜細節收斂在 Worker 與 WASM 一側。持續關注 d2js/js/CHANGELOG.md 即可跟蹤其后續演進而本文涉及的 index.d.ts、src/index.js 與 d2wasm/functions.go 則是深入理解其行為的三個最佳入口。【免費下載鏈接】d2D2 is a modern diagram scripting language that turns text to diagrams.項目地址: https://gitcode.com/GitHub_Trending/d2/d2創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考