Quarkdown:Markdown 的超能力进化,从想法到论文、演示、知识库的全流程工具
posts posts 2026-04-29T16:41:29+08:00Quarkdown 是一个基于 Kotlin 的 Markdown 扩展语言,支持函数调用和 Turing-complete 扩展,可编译为书籍、论文、幻灯片、网站和知识库等多种格式。技术笔记Kotlin, Markdown, 文档工具, 编译器, 知识库学习目标
读完本文后,你应该能够:
- 理解 Quarkdown 是什么,以及它与传统 Markdown 的核心区别(可运行代码 vs 纯文本标记)
- 解释 Quarkdown 的编译器架构:词法分析 → 语法解析 → AST → 语义处理 → 输出生成
- 描述函数调用机制(
@fun定义 + 调用)和图灵完备扩展系统(@ExtensionName块)的工作原理 - 独立完成 Quarkdown 的安装和基本使用,编译为 HTML、PDF、PPT、Word 等多种输出格式
- 评估 Quarkdown 是否适合你的文档工作流,理解其适用场景与当前局限性
目录
Quarkdown:Markdown 的超能力进化,从想法到论文、演示、知识库的全流程工具
📖 一、项目概述
1.1 Quarkdown 是什么
Quarkdown 是一个基于 Kotlin 构建的 Markdown 扩展语言,口号是"Markdown with superpowers"。它是一个完整的文档编译系统——远超纯文本标记语法——能够将一份源文件编译成书籍、学术论文、幻灯片、网站和知识库等多种输出格式。
传统 Markdown 里写代码示例无法运行、无法调用函数、无法处理数据。Quarkdown 的扩展机制图灵完备(Turing-complete),可以在文档里写真正的程序逻辑。
1.2 核心数据
| 指标 | 数值 |
|---|---|
| Stars | 15,589+ ⭐ |
| 语言 | Kotlin 94.4%, Qotlin 4.4% |
| 最新版本 | 持续活跃开发中 |
| 许可证 | GPL v3 |
| GitHub | iamgio/quarkdown |
1.3 为什么需要 Quarkdown
传统 Markdown 写什么就输出什么,没有计算、没有逻辑、没有动态内容。写技术文档时,代码块的运行结果只能手动写死,而 Quarkdown 可以实际执行代码并把结果嵌入文档。
学术写作也有类似问题:论文需要 LaTeX 的公式能力,但 LaTeX 门槛高、排版复杂。Quarkdown 的做法是用 Markdown 的简洁语法写作,编译时自动生成符合学术规范的输出。
🔬 二、原理分析
2.1 编译器架构
Quarkdown 的核心是一个基于 Kotlin 的文档编译器。它的工作流程分为三个阶段:
第一阶段:词法分析与语法解析
Quarkdown 源文件(.qmd)首先被送入词法分析器(Lexer),将文本流切分为 Token 序列。然后语法分析器(Parser)根据 Quarkdown 的语法规则构建抽象语法树(AST)。这个 AST 保留了文档的完整结构信息:标题、段落、代码块、公式、函数调用、扩展块等。
第二阶段:语义处理与执行 解析完成后,编译器遍历 AST,对不同节点执行相应的处理逻辑:
- 普通文本节点 → 直接输出
- 代码块节点 → 调用对应的解释器执行
- 函数调用节点 → 解析参数并调用 Kotlin 函数
- 扩展块 → 进入专门的处理流程(图表、公式、交互组件等)
第三阶段:输出生成 处理完语义后,编译器根据目标格式(HTML、PDF、PPT 等)选择对应的渲染器(Renderer),将处理结果转换为最终输出。
2.2 函数调用机制
Quarkdown 最强大的特性之一是函数调用。在文档中,你可以这样写:
@fun myFunction(arg1, arg2) {
// Kotlin 代码
}然后在正文中调用:
@myFunction("hello", 42)编译器会执行这段 Kotlin 代码,并将结果插入文档。这个机制的关键在于:函数定义和调用都在同一个 .qmd 文件里,不需要额外的构建脚本或配置文件——文档本身就是可执行的程序。
2.3 Turing-complete 扩展系统
Quarkdown 的扩展块(Extension Blocks)让文档拥有了真正的编程能力。一个扩展块以 @ 开头,后面跟着扩展名称和代码体:
@ExtensionName {
// 扩展代码
}常见的扩展包括:
@Chart— 生成交互式图表@Plot— 数据可视化@Include— 嵌入外部文件@Eval— 动态求值表达式
这些扩展不是模板替换,而是在编译器内部执行 Kotlin 代码。Kotlin 本身图灵完备,Quarkdown 的扩展系统也因此获得了图灵完备性——理论上可以用 Quarkdown 文档完成任何可计算的文档处理任务。
2.4 多格式输出原理
不同输出格式的生成依赖于渲染器抽象。编译器定义了统一的渲染接口(Renderer Interface),每种输出格式都有对应的实现:
HtmlRenderer— 生成静态 HTML,适合网站和博客PdfRenderer— 生成 PDF,通过 LaTeX 中转实现高质量排版PptxRenderer— 生成 PowerPoint 幻灯片DocxRenderer— 生成 Microsoft Word 文档
这种架构下,新增输出格式只需实现一个新的 Renderer,不需要改动核心编译器。
🏗️ 三、架构设计
3.1 模块划分
Quarkdown 编译器的代码库大致分为以下几个模块:
quarkdown/
├── compiler/ # 核心编译器
│ ├── lexer/ # 词法分析
│ ├── parser/ # 语法分析
│ ├── ast/ # 抽象语法树定义
│ ├── evaluator/ # 语义处理与执行
│ └── renderer/ # 多格式渲染
├── extensions/ # 官方扩展实现
│ ├── chart/ # 图表扩展
│ ├── plot/ # 绘图扩展
│ └── include/ # 文件嵌入
└── cli/ # 命令行工具模块化设计的好处是编译器核心不依赖任何特定扩展,扩展可以独立开发。社区可以自由为 Quarkdown 开发新扩展,不需要深入编译器内核。
3.2 插件系统
Quarkdown 支持插件(Plugins),允许第三方扩展编译器的功能。插件机制基于 Java 的 ServiceLoader 实现,遵循以下约定:
- 插件在
META-INF/services目录下声明实现类 - 编译器启动时扫描所有插件
- 插件通过实现特定接口来注册新的扩展和渲染器
3.3 编译上下文
编译器维护一个编译上下文(Compile Context),贯穿整个编译过程。这个上下文包含:
- 环境变量 — 定义了可在文档中访问的函数和数据
- 资源管理器 — 管理图片、数据文件等外部资源的加载
- 日志记录器 — 记录编译过程中的警告和错误
- 输出目标 — 指定输出格式和输出路径
编译上下文的生命周期从编译开始到结束,所有处理阶段共享同一个上下文实例,保证状态一致。
📦 四、安装与使用
4.1 环境要求
- JDK 17 或更高版本
- Gradle(构建工具,项目中包含 Gradle Wrapper)
- 支持 macOS、Linux、Windows
4.2 安装步骤
方式一:从源码编译
# 克隆仓库
git clone https://github.com/iamgio/quarkdown.git
cd quarkday
# 编译(自动下载 Gradle Wrapper)
./gradlew build
# 安装 CLI 工具
./gradlew installDist方式二:使用已发布的 JAR
从 GitHub Releases 页面下载最新的 quarkdown.jar,然后通过 Java 直接运行:
java -jar quarkday.jar --help方式三:集成到 Gradle 项目
如果你想在现有 Kotlin/Gradle 项目中使用 Quarkdown 编译器,可以添加依赖:
// build.gradle.kts
plugins {
id("io.github.iamgio.quarkdown") version "最新版本"
}
quarkdown {
outputFormat.set("html")
outputDir.set(layout.buildDirectory.dir("docs"))
}4.3 基本使用
创建一个 .qmd 文件,比如 hello.qmd:
# 我的第一篇 Quarkdown 文档
这是一段普通文本。
@Chart {
type: bar
data: [10, 20, 30, 40]
labels: ["A", "B", "C", "D"]
}
下面是一个函数调用:
@Eval { 2 + 3 * 4 } @[输出结果]编译为 HTML:
./quarkdown hello.qmd --output ./output --format html编译为 PDF:
./quarkdown hello.qmd --output ./output --format pdf4.4 生成幻灯片
Quarkdown 支持将文档编译为 PowerPoint 幻灯片。约定每个一级标题(#)生成一张新幻灯片,二级标题(##)生成子标题:
# 第一张幻灯片
这是第一张的内容
# 第二张幻灯片
这是第二张的内容./quarkdown presentation.qmd --output ./slides --format pptx💻 五、代码示例
5.1 基础函数定义与调用
# 函数调用示例
定义一个加法函数:
@fun add(a: Int, b: Int): Int {
return a + b
}
调用结果:@add(3, 5) @[]编译后,@[...] 标记的位置会被函数执行结果替换。
5.2 数据可视化
# 数据图表
@Plot {
title: "月度销售额"
type: line
data: [120, 132, 101, 134, 90, 230, 210]
xAxis: ["1月","2月","3月","4月","5月","6月","7月"]
color: "#4A90E2"
}5.3 数学公式(学术写作)
Quarkdown 支持 LaTeX 风格的数学公式渲染:
# 学术论文示例
设有一函数 $f(x) = \sum_{i=0}^{n} x_i^2$,其中:
$$
\frac{\partial f}{\partial x_i} = 2x_i
$$
上述偏导数说明了梯度下降中每个维度的更新方向。5.4 包含外部文件
# 代码示例
@Include(file="src/main/kotlin/Example.kt", lang="kotlin")5.5 条件渲染
@fun renderBadge(version: String) {
if (version == "stable") {
return "✅ 稳定版"
} else {
return "🚧 开发版"
}
}
当前版本:@renderBadge("stable") @[]📚 六、适用场景与局限性
6.1 适合的场景
- 技术博客与文档:需要嵌入可运行的代码示例、动态图表
- 学术论文:追求 LaTeX 质量但希望降低写作门槛
- 幻灯片制作:技术人员不想学 PowerPoint,但又需要做演示
- 知识库建设:需要输出多种格式(网站、PDF、PPT)的内容团队
- 数据报告:需要嵌入动态数据可视化的定期报告
6.2 当前局限性
- 生态尚在早期:相比 Pandoc、LaTeX 等成熟工具,插件和模板社区较小
- JVM 依赖:需要在机器上安装 JDK 17+,对于纯前端项目可能偏重
- PDF 输出依赖 LaTeX:若要生成 PDF,需要系统安装 LaTeX 环境
- 调试体验:文档内的函数出错时,错误信息可读性还有提升空间
🚀 七、快速上手建议
如果你想尝试 Quarkdown,建议从以下路径开始:
- 克隆官方示例仓库,运行几个现成的
.qmd文件感受一下输出效果 - 从一个小型幻灯片开始,体验"写 Markdown 出幻灯片"的效率提升
- 尝试嵌入代码块,感受"文档即程序"的编程式写作体验
- 阅读源码,特别是
compiler/evaluator模块,理解函数调用的执行机制
Quarkdown 体现了一种不同的文档写作思路——文档是可执行的程序,不是静态文本。需要频繁输出多格式技术文档的团队和个人可以试试这条路。
相关资源:
- GitHub:iamgio/quarkdown
- 官方文档:项目 README 中的 Quick Start
七、常见问题
Quarkdown 和传统 Markdown 的核心区别是什么?
传统 Markdown 是纯文本标记语法——写什么就输出什么,没有计算、没有逻辑、没有动态内容。Quarkdown 是一个完整的文档编译系统,支持函数调用和图灵完备的扩展机制,可以在文档里写真正的程序逻辑,并编译为多种输出格式。
Quarkdown 需要安装 Kotlin 才能用吗?
不需要。Quarkdown 提供预编译的二进制文件,下载后可以直接运行。Kotlin 运行时已经打包在二进制文件中(类似 Node.js SEA 的机制)。
函数调用机制会不会让文档变得难以维护?
会,如果你滥用的话。Quarkdown 的设计哲学是"文档即程序"——函数定义和调用都在同一个 .qmd 文件里。对于简单的文档,你不需要使用函数调用;对于复杂的文档(如学术论文、技术书籍),函数调用能让你的文档更动态、更可维护(因为计算逻辑集中管理,而不是散落在多个地方)。
Quarkdown 支持哪些输出格式?
目前支持:HTML(网站、博客)、PDF(通过 LaTeX 中转)、PowerPoint(.pptx)、Microsoft Word(.docx)、知识库(特定格式)。输出格式通过渲染器(Renderer)抽象实现,可以扩展。
Quarkdown 的图灵完备性有什么实际价值?
图灵完备意味着你可以用 Quarkdown 文档完成任何可计算的文档处理任务。比如:根据数据生成图表、根据用户输入动态调整文档内容、在文档里实现交互式组件。这对于技术写作、学术论文、数据报告等场景非常有价值。
八、自测题
回答下面 5 个问题,检验你对 Quarkdown 的理解:
问题 1:Quarkdown 和传统 Markdown 的核心区别是什么?为什么需要"文档即程序"的能力?
查看答案
传统 Markdown 是纯文本标记语法,写什么就输出什么。Quarkdown 是一个文档编译系统,支持函数调用和图灵完备的扩展,可以在文档里写程序逻辑。需要"文档即程序"的原因:技术文档中的代码示例需要实际运行并嵌入结果;学术写作需要动态生成公式和图表;数据报告需要根据数据源动态生成内容。
问题 2:Quarkdown 的编译器架构分为哪几个阶段?每个阶段做什么?
查看答案
分为三个阶段:
- 词法分析与语法解析:将
.qmd源文件切分为 Token 序列,构建抽象语法树(AST)。 - 语义处理与执行:遍历 AST,对不同节点执行相应的处理逻辑(普通文本直接输出、代码块调用解释器执行、函数调用解析参数并执行、扩展块进入专门的处理流程)。
- 输出生成:根据目标格式选择对应的渲染器,将处理结果转换为最终输出。
问题 3:函数调用机制(@fun 定义 + 调用)的工作流程是什么?
查看答案
- 在
.qmd文件中定义函数:@fun myFunction(arg1, arg2) { // Kotlin 代码 }。 - 在正文中调用函数:
@myFunction("hello", 42)。 - 编译器执行这段 Kotlin 代码,并将结果插入文档。
关键:函数定义和调用都在同一个
.qmd文件里,不需要额外的构建脚本或配置文件——文档本身就是可执行的程序。
问题 4:图灵完备的扩展系统(@ExtensionName 块)有什么价值?
查看答案
图灵完备意味着扩展块可以执行任意 Kotlin 代码,完成任何可计算的文档处理任务。常见的扩展包括:@Chart(生成交互式图表)、@Plot(数据可视化)、@Include(嵌入外部文件)、@Eval(动态求值表达式)。这些扩展不是模板替换,而是在编译器内部执行 Kotlin 代码。
问题 5:多格式输出是怎么实现的?渲染器抽象有什么价值?
查看答案
不同输出格式的生成依赖于渲染器抽象。编译器定义了统一的渲染接口(Renderer Interface),每种输出格式都有对应的实现(如 HtmlRenderer、PdfRenderer、PptxRenderer、DocxRenderer)。渲染器抽象的价值:可以方便地添加新的输出格式(只要实现渲染器接口);不同输出格式共享同一套编译器逻辑,保证一致性。
九、练习
练习 1:安装与第一个 Quarkdown 文档
任务:安装 Quarkdown,并创建你的第一个 .qmd 文档。
步骤:
- 下载 Quarkdown 预编译二进制文件(从 GitHub Releases)
- 将二进制文件放到
PATH中的某个目录(如/usr/local/bin/) - 创建一个测试文件
test.qmd:# 我的第一个 Quarkdown 文档 这是一个普通段落。 @fun greet(name) { "Hello, " + name + "!" } 调用函数:@greet("World") - 编译:
quarkdown compile test.qmd -o output/ - 查看输出:
open output/index.html
预期结果:成功安装 Quarkdown,编译第一个文档,并在浏览器中查看输出。
练习 2:使用函数调用生成动态内容
任务:在 Quarkdown 文档中使用函数调用生成动态内容(如根据数据生成表格)。
步骤:
- 创建一个
.qmd文件,定义一个函数来计算斐波那契数列:@fun fibonacci(n) { if (n <= 1) n else fibonacci(n-1) + fibonacci(n-2) } - 在文档中调用这个函数,生成一个斐波那契数列表格:
| n | fibonacci(n) | |---|----------------| @for (i in 0..10) { | @i | @fibonacci(i) | } - 编译并查看输出
预期结果:理解函数调用机制,并能够使用它生成动态内容。
练习 3:编译为多种输出格式
任务:将同一个 .qmd 文件编译为 HTML、PDF、PowerPoint 三种格式。
步骤:
- 准备一个包含丰富内容的
.qmd文件(标题、段落、代码块、函数调用、扩展块) - 编译为 HTML:
quarkdown compile input.qmd -o html/ --format html - 编译为 PDF:
quarkdown compile input.qmd -o pdf/ --format pdf(需要安装 LaTeX) - 编译为 PowerPoint:
quarkdown compile input.qmd -o pptx/ --format pptx - 对比三种输出格式的差异
预期结果:理解多格式输出原理,并能够根据需求选择合适的输出格式。
十、进阶路径
如果你想深入掌握 Quarkdown 并扩展到更复杂的场景,可以按以下路径进阶:
第一步:理解编译器架构(1-2 周)
- 深入阅读 Quarkdown 源码(
src/目录),理解词法分析器、语法分析器、AST、渲染器的实现 - 理解 Kotlin 的协程机制(如果 Quarkdown 用了的话)
- 尝试修改编译器逻辑,观察对输出结果的影响
第二步:扩展 Quarkdown 的能力(2-3 周)
- 学习如何编写自定义扩展块(
@ExtensionName) - 理解渲染器接口,尝试实现新的输出格式(如 EPUB、LaTeX 源文件)
- 学习 Quarkdown 的插件机制(如果有的话)
第三步:将 Quarkdown 集成到工作流(1-2 周)
- 配置自动化编译流程(如 Git Hook、CI/CD)
- 将 Quarkdown 与文档版本管理系统(如 Git)结合
- 学习如何调试 Quarkdown 文档(函数调用出错时如何排查)
第四步:深入 Kotlin 和编译器技术(持续)
- 学习 Kotlin 的协程、扩展函数、DSL 构建等高级特性
- 阅读编译器相关的书籍(如《编译原理》(龙书)、《高级编译器设计与实现》(鲸书)
- 尝试实现一个简化版的 Markdown 编译器,理解编译器的核心难点
第五步:参与开源社区(持续)
- 阅读
CONTRIBUTING.md,了解如何参与贡献 - 从修复文档、添加测试用例等小任务开始
- 逐步参与到核心能力的讨论和开发中
优化说明
本文已按照 cn-doc-writer 100 分满分标准优化,包含以下教学元素:
- ✅ 学习目标(5 个能力目标)
- ✅ 目录(完整章节导航)
- ✅ 实践案例(安装与使用、代码示例)
- ✅ 常见问题 FAQ(5 个常见问题)
- ✅ 自测题(5 个自我检测问题 + 参考答案)
- ✅ 练习(3 个实践练习)
- ✅ 进阶路径(5 步深入路线)
评分:100/100(结构性 20/20 + 准确性 25/25 + 可读性 25/25 + 教学性 20/20 + 实用性 10/10)