<-- Home |--rust

Math and Mermaid in Rustdoc中使用数学公式和Mermaid绘图

Rust神启动

又是Rust神启动的一天,今天我们要在Rustdoc中使用公式和Mermaid绘图。

本来我是准备蹭Cangjie的热度,搞一个领域数字化的自主可控、国产化替代、数智赋能、降本增效项目。就因为在知乎搞抽象,整了一个Rust更新那啥hosts文件,结果被带偏了。现在咋办呢?那不行,我要搞一个内存安全、开源可控、国产化替代、降本增效、数智赋能、自主可控的领域数字化项目。

反正就是要蹭,蹭上谁就是谁!

学Rust从哪里开始?

我以前听侯捷老师讲过一点点Rust,看过好几本Rust书的封面,还从没看过内容。从哪里开始学呢?

必然就是:doc.rust-lang.org

点开一看,不说别的,审美和一致性就让人不由得眼前一亮。虽然锈粉也干过很多抽象的事情,跟C/Cpp的Man page/Info比起来,Rust这个审美真是强迫症福音,没毛病。

特别是那个Rust API documentation,是我这几天学习的很重要的对象,导航比较清晰,还能直接看源代码。

就比如那个pub trait Copy,点进去一看。

Rust API documentation

这个帮助也是非常完善,上面有Source超链接,点进去一看,源代码是这样的:

1pub trait Copy: Clone {
2    // Empty.
3}

这就是个名字,还得回去看Clone的定义。恰好,前面的代码中间有Clone的定义,也可以点Clone

进去之后一样有源代码。

这么好的文档,不学Rust都对不起自己。原神启动!

API文档是怎么形成的?

Q: 这么好看的Rust API文档是怎么形成的?

A:Rust的API文档是根据源代码(注释)自动生成的。

好吧,这个答案并不让人意外。在Rust的源代码中,可以通过编写特殊的注释,来生成API文档。

1/// 这是一个示例
2///
3/// ```rust
4/// let x = 1;
5/// ```

而生成API文档的工具,就是rustdoc。有一本书:The rustdoc book,就是专门介绍rustdoc的。好好看去吧。

很快就发现,在lib.rs中,可以增加#[doc = include_str!("doc/doc.md")],来包含一个markdown文件。

并且,每个mod,也可以增加#[doc = include_str!("doc/mod.md")],来包含一个markdown文件。

这我就不困了……很快,蹭热度项目的代码的文档就开始起飞了……

每次编了一些文档,就可以运行:

1cargo rustdoc --open     # 可以这样
2cargo doc --open         # 或者这样

自动打开浏览器,就可以看到文档了。我喜欢把设计思路都写在文档中,然后一边看设计文档,一边改文档和代码。

紧接着,问题来了,我发现,这个被包含的md文件中的公式和Mermaid绘图,怎么就不好使了呢?

公式和Mermaid绘图

就比如说,我想要这样。行内公式、行间公式、Mermaid绘图。

Rust API documentation

解决方案

已知:可以在rustdoc中采用--html-in-header选项,来在head中增加内容到生成的网页中。一定要注意,这里的参数要放在--后面,这样的参数就是rustdoc的参数,而不是cargo的参数。

1cargo rustdoc --open -- --html-in-header my-header.html

这里就只能用rustdoc了,cargo doc不行。

那么对我这样的Javascript程序员来说,一切皆有可能了。。。

 1<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/katex.min.css"
 2    integrity="sha384-9eLZqc9ds8eNjO3TmqPeYcDj8n+Qfa4nuSiGYa6DjLNcv9BtN69ZIulL9+8CqC9Y" crossorigin="anonymous">
 3<script src="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/katex.min.js"
 4    integrity="sha384-K3vbOmF2BtaVai+Qk37uypf7VrgBubhQreNQe9aGsz9lB63dIFiQVlJbr92dw2Lx"
 5    crossorigin="anonymous"></script>
 6<script src="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/contrib/auto-render.min.js"
 7    integrity="sha384-kmZOZB5ObwgQnS/DuDg6TScgOiWWBiVt0plIRkZCmE6rDZGrEOQeHM5PcHi+nyqe"
 8    crossorigin="anonymous"></script>
 9
10<script>
11    document.addEventListener("DOMContentLoaded", function () {
12        renderMathInElement(document.body, {
13            delimiters: [
14                { left: "$$", right: "$$", display: true },
15                { left: "$", right: "$", display: false },
16            ]
17        });
18    });
19
20
21</script>
22
23
24<script type="module">
25    import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
26    mermaid.initialize({ startOnLoad: true }, "language-mermaid");
27    document.addEventListener("DOMContentLoaded", function () {
28        // iterate all language-mermaid, set its class to mermaid
29        const mermaidElements = document.querySelectorAll(".language-mermaid");
30        // set the class of all language-mermaid to mermaid
31        mermaidElements.forEach((element) => {
32            // filter html special characters
33            element.textContent = element.textContent.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
34            element.classList.add("mermaid");
35        });
36    });
37</script>

这个HTML就很容易的把katexmermaid的CSS和JS加载进来。

当然,现在我们的示例代码,就可以这样写:

1#![doc = include_str!("../README.md")]
2
3fn main() {
4    println!("Hello, world!");
5}

而对应的README.md,就可以这样写:

# 在Rustdoc中使用公式和Mermaid绘图

## 数学公式

$$
\arg\min_{x \in \mathbb{R}^3} f(x)
$$

其中,$\mathbb{R}^3$ 表示三维实数空间,$f(x)$ 表示一个函数。

## Mermaid绘图

```mermaid
graph LR
    A[Rust启动] --> B[Rust编译]
    B --> C[放弃]
```

完美!

完美之后的一点点不完美

现在,我们每次都要在运行cargo rustdoc后面增加参数-- --html-in-header rustdoc-header.html,太麻烦了。

所幸,Cargo还提供了配置的方式,在Cargo.toml同一个目录下面,或者在需要特殊出路的mod目录下面,增加一个配置文件夹.cargo,在这个文件夹中增加一个config.toml文件,就可以配置rustdoc了。

1[alias]
2d = "rustdoc --open"
3
4[build]
5rustdoc = "rustdoc"
6rustdocflags = ["--html-in-header", "../rustdoc-header.html"]

这样,我们每次运行cargo rustdoc,就会自动增加--html-in-header rustdoc-header.html参数。

另外,我们还整了一个别名d,这样就可以直接运行cargo d,来打开浏览器查看文档了。注意这里如果把-- --html-in-header ../rustdoc-header.html写在别名定义的后面,那么后面的[build]的配置就可以不要了。一次提供两个解决方案!

完美!

总结

Rust的API文档是根据源代码自动生成的。

在Rustdoc中使用公式和Mermaid绘图,可以通过配置rustdoc-header.html来实现。

在Cargo中配置config.toml,可以自动增加--html-in-header rustdoc-header.html参数。


文章标签

|-->rust |-->cargo |-->rustdoc |-->math |-->mermaid |-->katex |-->markdown |-->数学公式 |-->Mermaid绘图


GitHub