limu 是一个用 Rust 和 Go 编写的图表布局引擎。它读取 Mermaid,把绘制交给你的程序。

工作方式

Mermaid 和 Pele(limu 移植自这个 Mermaid 渲染器)布局一张图表后,把它写成 SVG,交给浏览器绘制。

SVG 渲染器

limu 早一步停下,停在场景(scene)。场景是以数据表示的、已经布局好的图表。它记录每个部分是什么、在哪里,但不记录它长什么样。之后由后端来绘制。limu 提供的后端有在 GPU 上绘制的 GPUI 和 MyGo,绘制到位图的 tiny-skia 和 Core Graphics,绘制到终端字符格的后端,以及 SVG。你也可以自己写一个。

limu

场景里没有颜色,所以只需布局一次,就能用任意多种方式绘制。切换主题只需重绘,后端也可以按自己的方式绘制每个部分。

同一个场景,只布局一次,用四种方式绘制

场景 只有方框、路径和标签,没有样式。

approvereviseDraftReviewShip

Kohu 用 limu 的浅色主题绘制。

用 limu 的浅色主题绘制。

KohuDark 只换了颜色。

只换了颜色。

Liquid Glass 每个部分按自己的方式绘制,用的是 MyGo 的玻璃效果。

每个部分按自己的方式绘制,用的是 MyGo 的玻璃效果。

后端还可以更进一步,为自己的外观重新布局图表。mygo-platinum 就这样为 Platinum 桌面绘制图表。

Platinum 用点阵字体重新布局,逐像素绘制。

用点阵字体重新布局,逐像素绘制。

应用还可以向场景查询指针下方是哪个部分。

在应用中使用 limu

cargo add limu limu-gpui

limu-gpui 在 GPUI 窗口中绘制场景,和窗口的其余部分一起在 GPU 上绘制,并用 GPUI 的文本系统测量文本。场景能告诉你指针下方是哪个部分。

// 用窗口的文本系统测量文本。let measurer = TextMeasurer::new(window, Fonts::default());let layout = limu::layout::Options {    measurer: &measurer,    ..Default::default()};let scene = limu::layout(src, &layout)?;// 在 canvas 的绘制闭包中绘制场景,并找出某一点上的部分。let o = Options {    look: Look::new(Theme::KOHU_DARK),    ..Options::default()};paint(&scene, &o, bounds.origin, 1.0, window, cx);if let Some(i) = scene.item_at(at, 4.0) {    let it = &scene.items[i];    println!("clicked {} {:?}", it.role.as_str(), it.id);}
go get github.com/firede/limu/limumygo

limumygo 用 MyGo 的原生 UI 在 GPU 上绘制场景,并告诉你指针下方是哪个部分。布局时要用绘制时的同一套字体。

fonts := limumygo.DefaultFontssc, err := limu.Layout(src, &layout.Options{Measurer: fonts})if err != nil {	return err}// 在视图中绘制图表,并查看点击了哪个部分。w := limumygo.View(c, sc, &limumygo.Options{	Look:  style.Look{Theme: style.KohuDark()},	Fonts: fonts,})if it := w.Clicked(); it != nil {	fmt.Println("clicked", it.Role, it.ID)}

继续阅读

limu 与 Pele

limu 逐个函数移植自 Pele,后者是 Obsidian 团队开发的小巧、快速的 Mermaid 渲染器。共有两个移植版,Rust 版 limu-rs 和 Go 版 limu。两者的测试都逐个数值检查布局是否与 Pele 一致。两者都以 MIT 许可证开源,见 Rust 版和 Go 版。

Pele 得名于夏威夷的火山女神。Limu 在夏威夷语中指海里的藻类。本站的配色取自 limu kohu,一种生长在潮池里的红藻。