25 个版本 (3 个重大更新)
1.0.0-alpha.20 | 2024 年 8 月 13 日 |
---|---|
1.0.0-alpha.18 | 2024 年 7 月 2 日 |
1.0.0-alpha.16 | 2023 年 12 月 5 日 |
1.0.0-alpha.15 | 2023 年 11 月 20 日 |
0.0.1 | 2015 年 1 月 25 日 |
#14 在 解析器实现 中
43,931 每月下载量
在 146 个 包中使用 (85 直接)
1MB
27K SLoC
markdown-rs
👉 注意:这是一个重用旧名称的新包。旧包(版本 0.3.0 及以下)存在一些问题。请确保使用新包,目前处于 alpha 版本,版本号为
1.0.0-alpha.20
。
Rust 中的 CommonMark 兼容 Markdown 解析器,带有 AST 和扩展功能。
功能亮点
- 兼容 (100% 符合 CommonMark)
- 扩展 (100% GFM,100% MDX,frontmatter,数学公式)
- 安全 (100% 安全 Rust,默认 100% 安全 HTML)
- 健壮 (2300+ 测试,100% 覆盖率,模糊测试)
- AST (mdast)
何时使用此工具?
- 如果您只想将 Markdown 转换为 HTML(可能包含一些扩展)
- 如果您想对 Markdown 进行非常复杂的操作
这是什么?
markdown-rs
是一个用 Rust 编写的开源 Markdown 解析器。它作为一个状态机实现,生成具体的令牌,确保每个字节都被计算,并带有位置信息。API 将此信息作为 AST 暴露出来,这使其更容易处理,或者它可以直接编译为 HTML。
虽然大多数Markdown解析器都致力于符合CommonMark(或GFM),但本项目通过遵循参考解析器(cmark
、cmark-gfm
)的工作方式进一步发展,并通过数千次额外测试得到验证。
除了CommonMark和GFM之外,本项目还支持Markdown的常见扩展,如MDX、数学和frontmatter。
这个Rust crate有一个在JavaScript中的兄弟项目:micromark
(以及mdast-util-from-markdown
用于AST)。
提示:如果您想编译MDX,请使用mdxjs-rs
。
问题
内容
安装
使用Rust(rust edition 2018+,±版本1.56+),使用cargo
安装
cargo add markdown@1.0.0-alpha.20
👉 注意:这是一个重用旧名称的新包。旧包(版本 0.3.0 及以下)存在一些问题。请确保使用新包,目前处于 alpha 版本,版本号为
1.0.0-alpha.20
。
使用
fn main() {
println!("{}", markdown::to_html("## Hello, *world*!"));
}
输出
<h2>Hello, <em>world</em>!</h2>
扩展(在这种情况下是GFM)
fn main() -> Result<(), markdown::message::Message> {
println!(
"{}",
markdown::to_html_with_options(
"* [x] contact@example.com ~~strikethrough~~",
&markdown::Options::gfm()
)?
);
Ok(())
}
输出
<ul>
<li>
<input checked="" disabled="" type="checkbox" />
<a href="mailto:contact@example.com">contact@example.com</a>
<del>strikethrough</del>
</li>
</ul>
语法树(mdast)
fn main() -> Result<(), markdown::message::Message> {
println!(
"{:?}",
markdown::to_mdast("# Hey, *you*!", &markdown::ParseOptions::default())?
);
Ok(())
}
输出
Root { children: [Heading { children: [Text { value: "Hey, ", position: Some(1:3-1:8 (2-7)) }, Emphasis { children: [Text { value: "you", position: Some(1:9-1:12 (8-11)) }], position: Some(1:8-1:13 (7-12)) }, Text { value: "!", position: Some(1:13-1:14 (12-13)) }], position: Some(1:1-1:14 (0-13)), depth: 1 }], position: Some(1:1-1:14 (0-13)) }
API
markdown-rs
公开了to_html
、to_html_with_options
、to_mdast
、Options
以及一些其他结构和枚举。
有关更多信息,请参阅crate文档。
扩展
markdown-rs
支持扩展到CommonMark
。这些扩展由本项目维护。它们默认未启用,但可以通过选项打开。
- frontmatter
- GFM
- 自动链接文本
- 脚注
- 删除线
- 表格
- 标签过滤器
- 任务列表项
- 数学
- MDX
- ESM
- 表达式
- JSX
本项目的目标不是支持许多不同的扩展,而是支持非常常见且基本标准化的扩展。
项目
markdown-rs
作为一个单一代码库维护。
概述
解析Markdown的过程如下
markdown-rs
+-------------------------------------------------+
| +-------+ +---------+--html- |
| -markdown->+ parse +-events->+ compile + |
| +-------+ +---------+-mdast- |
+-------------------------------------------------+
文件结构
src/
中的文件如下
construct/*.rs
— Markdown中使用的CommonMark、GFM和其他扩展结构util/*.rs
— 解析Markdown时经常需要的辅助工具event.rs
— 发生在某个地方有意义的事情lib.rs
— 公共APImdast.rs
— 语法树parser.rs
— 将Markdown字符串转换为事件resolve.rs
— 处理事件的步骤state.rs
— 状态机的步骤subtokenize.rs
— 处理其他内容中的内容to_html.rs
— 将事件转换为HTML字符串to_mdast.rs
— 将事件转换为语法树tokenizer.rs
— 将状态机的状态粘合在一起unist.rs
— 指针和位置,在mdast中使用
测试
markdown-rs
使用了 ~650 个 CommonMark 测试以及超过 1k 个与 CM 引用解析器确认的额外测试。然后还有更多针对 GFM 和其他扩展的测试。这些测试涵盖了代码的各个分支,这意味着这个项目拥有 100% 的代码覆盖率。模糊测试用于检查可能未覆盖到的部分。
以下 bash 脚本在处理此项目时很有用:
- 生成代码(最新的 CM 测试和 Unicode 信息)
cargo run --manifest-path generate/Cargo.toml
- 运行示例
RUST_BACKTRACE=1 RUST_LOG=trace cargo run --features log --example lib
- 格式化
cargo fmt && cargo fix --all-targets
- lint
cargo fmt --check && cargo clippy --examples --tests --benches --all-features
- 测试
RUST_BACKTRACE=1 cargo test
- 文档
cargo doc --document-private-items
- 模糊测试
cargo install cargo-fuzz cargo install honggfuzz cargo +nightly fuzz run markdown_libfuzz cargo hfuzz run markdown_honggfuzz
版本
markdown-rs
遵循 SemVer。
安全
通常讨论的 markdown 安全方面是 跨站脚本(XSS)攻击。如果 markdown 不包含嵌入的 HTML 或危险的协议(如 javascript:
或 data:
)的链接/图像,那么 markdown 本身是安全的。markdown-rs
默认将任何 markdown 转换为安全版本,即使 HTML 已嵌入或使用了危险的协议,因为它会编码或丢弃它们。启用 allow_dangerous_html
或 allow_dangerous_protocol
选项将使用户提供的 markdown 暴露于 XSS 攻击。
与 XSS 安全相关的一个方面是语法错误:markdown 本身没有语法错误。一些语法扩展(特别是,只有 MDX)包含语法错误。因此,to_html_with_options
返回 Result<String, Message>
,其中的错误是一个结构,指示问题发生的位置、发生的情况以及期望的情况。在使用 MDX 时,请确保处理错误。
另一个安全方面是 DDoS 攻击。例如,攻击者可以向 markdown-rs
抛出一个 100mb 的文件,在这种情况下,完成它将花费很长时间。也有可能用更小的负载使 markdown-rs
崩溃,特别是当打开成千上万的链接、图像、强调或加粗而未关闭时。明智的做法是限制接受的输入大小(500kb 可以存放一本大书),并在不同的线程中处理内容,以便在需要时停止。
有关 markdown 清洗的更多信息,请参阅 improper-markup-sanitization.md
,由 @chalker 提供。
贡献
有关帮助的方法,请参阅 contributing.md
。有关获得帮助的方法,请参阅 support.md
。有关如何在项目内部和周围进行沟通的信息,请参阅 code-of-conduct.md
。
赞助
通过赞助此努力并回馈以支持
- GitHub Sponsors(个人;每月或一次性)
- OpenCollective 或 GitHub Sponsors(统一;每月或一次性)
感谢
特别感谢
- Vercel 为初始开发提供资金
- @Murderlon 为标志设计
- @johannhof 为存储库名称