项目打包
基于 MoonBit 语言的 Markdown to HTML 转换工具库。
一个纯 MoonBit 编写的 Markdown 解析与 HTML 渲染库,为 MoonBit 生态提供文档渲染能力。开发者可将其集成到 Web 应用、静态站点生成器、代码编辑器预览面板等场景中。
# H1
###### H6
*italic*
**bold**
`code`
```
[text](url)
[text](url "title")

- item
* item
+ item
1. item
> quote
---
***
___
\*
\[
<span>
<div>
| A | B |
- [x] done
- [ ] todo
~~strikethrough~~
```rust
https://example.com
<span class="hl-*">
---\ntitle: ...\n---
[^1]
::: tip
::: warning
方式一:作为 MoonBit 项目依赖(推荐)
在目标项目的 moon.pkg 中添加依赖:
moon.pkg
import { "moonbit-texteditor/src" @md, }
然后运行 moon update 自动拉取。如果包已发布到 mooncakes.io:
moon update
moon add moonbit-texteditor
方式二:从源码构建
git clone https://github.com/lexchb/moonbit-Texteditor.git cd moonbit-Texteditor moon build # 构建原生目标 moon build --target js # 构建 JS 目标(浏览器使用)
CLI 演示程序 — 展示所有支持的 Markdown 功能:
moon run cmd/main
Web 交互式演示 — 实时 Markdown 编辑器:
直接在浏览器中打开项目根目录下的 demo.html(需要本地 HTTP 服务器):
demo.html
# Python python -m http.server 8000 # Node.js npx serve . # 然后访问 http://localhost:8000/demo.html
本库提供从 parse(解析)到 render(渲染)的完整转换链路。
parse
render
let html = @md.render_to_string("# Hello World") // => "<h1>Hello World</h1>"
let opts = @md.create_markdown_options( true, // enable_gfm_tables true, // enable_gfm_tasklist true, // enable_gfm_strikethrough true, // enable_gfm_autolink true, // enable_syntax_highlight false, // hard_wrap ) let html = @md.render_to_string_with_opts("~~text~~", opts) // => "<p><del>text</del></p>"
// 第一步:解析 Markdown 为 AST let blocks = @md.parse("## Title\n\nSome **bold** text") // 第二步:手动检查和操作 AST match blocks[0] { Heading(level, inlines) => println("Heading level: " + level.to_string()) _ => () } // 第三步:渲染为 HTML let html = @md.render(blocks)
let input = "---\ntitle: My Doc\nauthor: Alice\n---\n\n# Content" let (metadata, body) = @md.parse_frontmatter(input) // metadata = [("title", "My Doc"), ("author", "Alice")] // body = "# Content"
let blocks = @md.parse("# A\n\n## B\n\n### C") let toc = @md.generate_toc(blocks) // toc = [(1, "A"), (2, "B"), (3, "C")]
let highlighted = @md.highlight_code("fn main() {}", "rust") // => "<span class=\"hl-keyword\">fn</span> main() {}"
fn main { let input = "# Markdown 示例\n\n" + "这是一个包含 **加粗** 和 *斜体* 的段落。\n\n" + "| 表格 | 列2 |\n" + "|------|-----|\n" + "| 单元格1 | 单元格2 |\n\n" + "- [x] 已完成任务\n" + "- [ ] 未完成任务\n" // 创建选项:启用表格、任务列表、删除线 let opts = @md.create_markdown_options( true, true, true, true, true, false, ) let html = @md.render_to_string_with_opts(input, opts) println(html) }
parse(input)
String
Array[Block]
parse_with_opts(input, opts)
String, MarkdownOptions
render(blocks)
render_to_string(input)
render_to_string_with_opts(input, opts)
render_html_with_opts(blocks, opts)
Array[Block], MarkdownOptions
parse_frontmatter(input)
(Array[(String,String)], String)
generate_toc(blocks)
Array[(Int, String)]
create_markdown_options(...)
6 × Bool
MarkdownOptions
default_options()
highlight_code(code, lang)
String, String
escape_html(s)
┌─────────────────────────────────────────────────────┐ │ 用户 API │ │ parse() / render() / render_to_string() │ ├─────────────────────────────────────────────────────┤ │ Option 层 (扩展语法) │ │ GFM 表格 / 任务列表 / 删除线 / 语法高亮 │ ├─────────────────────────────────────────────────────┤ │ InlineParser │ │ 强调 / 代码 / 链接 / 图片 / HTML / 转义 / 自动链接 │ ├─────────────────────────────────────────────────────┤ │ BlockParser │ │ 标题 / 段落 / 列表 / 代码块 / 引用 / 水平线 / 表格 │ ├─────────────────────────────────────────────────────┤ │ Tokenizer / Lexer │ │ 行级分块 / 围栏检测 / 缩进分析 / 转义预处理 │ ├─────────────────────────────────────────────────────┤ │ AST 类型定义 │ │ Block / Inline 枚举体系 │ └─────────────────────────────────────────────────────┘
moonbit-texteditor/ ├── moon.mod.json # 项目配置 ├── src/ │ ├── moon.pkg.json # 包配置 │ ├── ast.mbt # AST 类型定义(核心数据结构) │ ├── lexer.mbt # 词法分析:行分类、缩进计算、围栏检测 │ ├── block_parser.mbt # 块级解析器 │ ├── inline_parser.mbt # 内联解析器 │ ├── renderer_html.mbt # HTML 渲染器 │ ├── renderer.mbt # 渲染器 trait 定义(方便扩展其他输出) │ ├── options.mbt # 解析选项配置 │ ├── syntax_highlight.mbt # 语法高亮引擎 │ ├── lib.mbt # 统一入口 API │ └── utils.mbt # 工具函数 ├── cmd/main/ │ ├── moon.pkg.json # CLI demo 包配置 │ └── main.mbt # CLI 演示程序(13 个功能场景) ├── web/ │ ├── moon.pkg.json # Web 包配置 │ └── main.mbt # 浏览器端 JS 桥接入口 ├── demo.html # 交互式 Web 演示页面 └── .github/workflows/ ├── ci.yml # CI(check / build / test) └── copilot-setup-steps.yml # Copilot 环境配置
// === Block 节点类型 === enum Block { // 文档根节点 Document(Array[Block]) // 段落 Paragraph(Array[Inline]) // 标题 (level: 1-6) Heading(Int, Array[Inline]) // 无序列表 BulletList(Array[ListItem], Bool) // 是否紧凑 // 有序列表 OrderedList(Array[ListItem], Int, Bool) // 起始序号, 是否紧凑 // 列表项 ListItem(Bool, Array[Block]) // 是否已勾选(任务列表) // 代码块(围栏式) FencedCodeBlock(String?, String) // 语言, 内容 // 代码块(缩进式) IndentedCodeBlock(String) // 块引用 BlockQuote(Array[Block]) // 水平线 ThematicBreak // HTML 块 HtmlBlock(String) // 表格(GFM) Table(Array[TableRow]) // 空行 BlankLine } // === Inline 节点类型 === enum Inline { // 纯文本 Text(String) // 软换行 SoftBreak // 硬换行 LineBreak // 斜体 Emphasis(Array[Inline]) // 加粗 Strong(Array[Inline]) // 删除线(GFM) Strikethrough(Array[Inline]) // 行内代码 Code(String) // 链接 Link(Array[Inline], String, String?) // 文本, URL, title // 图片 Image(String, String, String?) // alt, src, title // HTML 内联 HtmlInline(String) // 自动链接 AutoLink(String, Bool) // URL / Email }
ast.mbt
Block
Inline
Show
lexer.mbt
enum LineType { Heading(Int) // # ## ### ... FenceStart(String?) // ``` 或 ~~~,可选语言 FenceEnd BulletItem(String) // - * + OrderedItem(Int) // 1. BlockQuote ThematicBreak Empty IndentedCode TableRow Paragraph } struct Line { typ : LineType content : String indent : Int line_number : Int }
block_parser.mbt
Line[]
Block[]
struct BlockParser { lines : Array[Line] mut pos : Int } fn parse(lines : Array[Line]) -> Array[Block]
inline_parser.mbt
Array[Inline]
struct Delimiter { char : Char // * 或 _ is_close : Bool is_open : Bool position : Int length : Int // 1 或 2 }
renderer_html.mbt
StringBuilder
<+
fn render_block(block : Block, buf : StringBuilder) -> Unit fn render_inline(inline : Inline, buf : StringBuilder) -> Unit
options.mbt
struct MarkdownOptions { // 启用/禁用特定语法 enable_gfm_tables : Bool = false enable_gfm_tasklist : Bool = false enable_gfm_strikethrough : Bool = false enable_gfm_autolink : Bool = false enable_syntax_highlight : Bool = false // 渲染选项 line_width : Int = 80 hard_wrap : Bool = false // 是否将软换行转为 <br> }
lib.mbt
/// 将 Markdown 字符串解析为 Block AST pub fn parse(input : String) -> Array[Block] /// 将 Block AST 渲染为 HTML 字符串 pub fn render(blocks : Array[Block]) -> String /// 解析 + 渲染一站式调用 pub fn render_to_string(input : String) -> String /// 带选项的解析 pub fn parse_with_opts(input : String, opts : MarkdownOptions) -> Array[Block] /// 带选项的渲染 pub fn render_to_string_with_opts(input : String, opts : MarkdownOptions) -> String
renderer.mbt
utils.mbt
gfm/table.mbt
gfm/task_list.mbt
gfm/strikethrough.mbt
gfm/autolink.mbt
test/*.mbt
bench/benchmark.mbt
核心部分约 8.3k 行,不含测试为 ~9.9k,含全部扩展约 ~11.9k。可根据进度灵活裁剪 GFM 扩展以控制代码量在 4~10k 范围内。
单元测试 → 集成测试 → CommonMark 规范测试
输入: "# Hello" 输出: "<h1>Hello</h1>" 输入: "**bold** and *italic*" 输出: "<p><strong>bold</strong> and <em>italic</em></p>" 输入: "- item 1\n- item 2" 输出: "<ul>\n<li>item 1</li>\n<li>item 2</li>\n</ul>" 输入: "> quote\n>\n> more" 输出: "<blockquote>\n<p>quote</p>\n<p>more</p>\n</blockquote>"
enum
match
write_string
trait
raise
本项目基于 CommonMark 0.31 规范 和 GitHub Flavored Markdown (GFM) 规范 使用 MoonBit 语言进行原创实现。
https://spec.commonmark.org/0.31/
本项目的解析逻辑直接基于 CommonMark 规范文档中的算法描述实现,未直接复制或移植任何现有开源项目的源代码。
Apache License 2.0
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
moonbit-texteditor
基于 MoonBit 语言的 Markdown to HTML 转换工具库。
项目定位
一个纯 MoonBit 编写的 Markdown 解析与 HTML 渲染库,为 MoonBit 生态提供文档渲染能力。开发者可将其集成到 Web 应用、静态站点生成器、代码编辑器预览面板等场景中。
与赛题要求的对应
一、功能范围
第一阶段:CommonMark 核心语法(必做)
# H1~###### H6*italic***bold**`code`、代码块(缩进/围栏```)[text](url)[text](url "title")- item/* item/+ item1. item> quote(支持嵌套)---***___\*\[等反斜杠转义<span>、块级<div>第二阶段:GFM 扩展语法
| A | B |- [x] done- [ ] todo~~strikethrough~~```rusthttps://example.com第三阶段:增强功能
<span class="hl-*">包裹---\ntitle: ...\n---)[^1]风格脚注::: tip/::: warning安装与使用
环境要求
安装方式
方式一:作为 MoonBit 项目依赖(推荐)
在目标项目的
moon.pkg中添加依赖:然后运行
moon update自动拉取。如果包已发布到 mooncakes.io:方式二:从源码构建
运行示例
CLI 演示程序 — 展示所有支持的 Markdown 功能:
Web 交互式演示 — 实时 Markdown 编辑器:
直接在浏览器中打开项目根目录下的
demo.html(需要本地 HTTP 服务器):使用方法
本库提供从
parse(解析)到render(渲染)的完整转换链路。基础用法 — 一句话转换
带选项用法 — 控制 GFM 扩展开关
分步用法 — 解析 AST → 手动处理 → 自定义渲染
解析 Frontmatter 元数据
生成目录 (TOC)
语法高亮(单独使用)
完整示例
API 速查
parse(input)StringArray[Block]parse_with_opts(input, opts)String, MarkdownOptionsArray[Block]render(blocks)Array[Block]Stringrender_to_string(input)StringStringrender_to_string_with_opts(input, opts)String, MarkdownOptionsStringrender_html_with_opts(blocks, opts)Array[Block], MarkdownOptionsStringparse_frontmatter(input)String(Array[(String,String)], String)generate_toc(blocks)Array[Block]Array[(Int, String)]create_markdown_options(...)6 × BoolMarkdownOptionsdefault_options()MarkdownOptionshighlight_code(code, lang)String, StringStringescape_html(s)StringString二、架构设计
整体架构
模块划分
核心数据结构设计
三、各模块详细说明
3.1 AST 类型定义 (
ast.mbt)Block和Inline枚举体系Showtrait 实现,方便调试输出3.2 词法分析器 (
lexer.mbt)3.3 块级解析器 (
block_parser.mbt)Line[]转换为Block[](AST)3.4 内联解析器 (
inline_parser.mbt)Array[Inline]3.5 HTML 渲染器 (
renderer_html.mbt)StringBuilder(MoonBit v0.10 已有)高效拼接<+提升可读性3.6 选项系统 (
options.mbt)3.7 统一 API (
lib.mbt)四、代码量估算
ast.mbtlexer.mbtblock_parser.mbtinline_parser.mbtrenderer_html.mbt+renderer.mbtoptions.mbtlib.mbtutils.mbtgfm/table.mbtgfm/task_list.mbtgfm/strikethrough.mbtgfm/autolink.mbttest/*.mbtbench/benchmark.mbt核心部分约 8.3k 行,不含测试为 ~9.9k,含全部扩展约 ~11.9k。可根据进度灵活裁剪 GFM 扩展以控制代码量在 4~10k 范围内。
五、开发路线图
Phase 1:基础设施与核心解析(第 1~2 周)
ast.mbt中的Block/Inline枚举lexer.mbt:行分类 + 缩进分析block_parser.mbt基础能力:inline_parser.mbt基础能力:Phase 2:核心内联语法(第 3 周)
Phase 3:复杂块级结构(第 4 周)
Phase 4:GFM 扩展(第 5 周)
Phase 5:测试与优化(第 6 周)
六、测试策略
测试层级
测试用例覆盖
七、技术要点与风险控制
MoonBit 特性利用
enum+matchStringBuilder<+模板写入语法write_string调用traitraise错误处理潜在风险与应对
原创或移植说明
本项目基于 CommonMark 0.31 规范 和 GitHub Flavored Markdown (GFM) 规范 使用 MoonBit 语言进行原创实现。
参考来源
https://spec.commonmark.org/0.31/本项目的解析逻辑直接基于 CommonMark 规范文档中的算法描述实现,未直接复制或移植任何现有开源项目的源代码。
本项目许可证
Apache License 2.0
设计与实现特点
enum+match类型系统和测试方式组织代码,而不是复刻 C/JavaScript 的函数式风格;StringBuilder和模式匹配替代;