ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

D2.js 演进全解析:从首个公开版本到 d2-config 的能力矩阵与源码实现

D2.js 演进全解析:从首个公开版本到 d2-config 的能力矩阵与源码实现 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),仅供参考
返回列表