利用 Kotlin DSL 的强大功能编写文档
目录
本文最初发表于在阿姆斯特丹举办的 API The Docs 会议上,这项活动重点关注开发者成功以及 API 文档和开发者门户对企业的帮助。 我们向想要提升技术写作相关能力的读者强烈推荐这场会议。 所有演讲都很实用,信息丰富,并包括现场演示。
有时,几行代码就可以帮助您完成文档任务。 但是,文档不是代码,在编写文档时添加外部功能或自动化可能会更困难。 如果能像编写代码一样编写文档,完成特定任务,然后将代码转换回文档就好了!
在这篇博文中,我们将探讨如何使用 Kotlin DSL 编写文档来做到这一点。
DSL? 什么是 DSL?
我们来定义“领域专用语言”,即 DSL。
简单来说,它是一种专用于解决特定问题的编程语言。 这些语言的概念和规则特定于具体领域。
DSL 也称为小语言或面向问题的语言。 这些定义更好地描述了其本质 – DSL 专为解决特定问题而设计。
DSL 有两种类型。 外部 DSL 是独立语言,具有自己的语法、词法分析器和解析器。 SQL 就是这种语言的一个例子。 内部 DSL 则重用通用语言的语法和解析器,并利用该语言的可用扩展选项。
适用于文档的 Kotlin DSL 属于内部 DSL 类别。
使用 Kotlin,您可以构建具有外部 DSL 外观的内部 DSL。 因此,我们开发的是专为文档设计的内部 DSL。
在 JetBrains MPS 网站 上详细了解外部 DSL 与内部 DSL 之间的差异。
Kotlin DSL 的本质
适用于文档的 Kotlin DSL 是专为创建文档和静态网站而设计的框架。
框架是在基本文档元素上运行的类型安全构建器,额外功能作为用户代码或外部依赖项插入。 从特定源或输出格式到自然语言处理,依赖项可以提供任何类型的功能。
借助 Kotlin DSL,技术文档撰写人可以定义语义元素,例如章节、过程、表、列表等。 虽然 DSL 最初关注我们自己的标记,但其灵活性允许自定义扩展,因此理论上,我们可以将任何输入格式转换为任何输出格式。
在元素层面,用户可以将复杂逻辑封装在自定义元素中,然后像段落或列表一样简单使用。
Kotlin DSL 的一大显著优势是 IntelliJ IDEA 等集成式开发环境 (IDE) 已提供内置支持,包括错误检查、代码补全和重构。 这非常有助于提高书面内容的质量。
重复项检测运作方式示例
由于源是常规 Kotlin 代码,所有代码智能和语言支持功能均开箱即用。 需要浏览代码? 检测死代码和重复代码? 或者将另一种语言注入字符串文字? 这些 IDE 功能全都适用于 Kotlin DSL。 语言本身提供了显著好处,例如完整的静态类型和实用工具生态系统。
这篇博文展示了 DSL 如何生成自定义 XML 标记,但请注意,它也可以根据您的具体需求生成多种输出格式,例如 HTML 或 .docx。
此外,DSL 不仅可以在 IntelliJ IDEA 中使用,还可以在其他编辑器中甚至通过命令行使用。 它提供了与编写内容类似的体验,同时还利用了 Kotlin 编程语言的无限可能。
以下是我们标记的一些示例。
在第一个示例中,我们创建一个段落和一个包含两个列表条目的列表,并在这些元素内附加一些内容。
val content = StardustDslContentProvider { p { +"Hello, DSL"} list { li { +"List item 1" } li { +"List item 2" } } this }
运行脚本后,结果如下:

在第二个示例中,我们创建一个包含两列的表。
val content = StardustDslContentProvider { table { tr { td { +"Parameter name" } td { +"Parameter type" } } tr { td { +"Value 1" } td { +"Value 2" } } this }
变为:

在第三个示例中,我们演示如何注入任何其他语言,例如 XML 或 Markdown。 在下面的示例中,我们注入一个包含三个步骤的过程:
xml(""" <procedure title="Title"> <step>Step 1</step> <step>Step 2</step> <step>Step 3</step> </procedure> """)
结果如下:

当然,仅用标记编写很难说是突破性成就。 那么,我们就来看一些更创新、更有趣的内容。
演示
首先,请注意,我们想展示的是方式,而不是具体实现。 以下演示使用我们的自定义 XML 标记执行,但我们可以桥接任何其他格式,例如 AsciiDoc、Markdown、reStructuredText、LaTeX 到 HTML,甚至是 .docx。
我们方式的三大关键优势
关注点分离
我们谈论了很多将内容与其表示分离的话题。 这种方式从 CSS 早期就存在于 Web 开发领域,后在轻量级标记语言中得到重新解释和强化。 这项技术涉及将文档的视觉和设计方面与其内容和结构分离。 这样一来,文档撰写人可以专注于内容,同时轻松调整其表示。
但我们可以更进一步,将数据与其表示分离。 文档可以基于数据本身生成,而不是基于与所述事物没有直接关系的标记。 我们可以从应用程序运行时获取数据,然后定义其表示。
此外,我们可以根据数据设计使表示具有条件。
例如,如果方法描述表明其已被弃用,则将其转换为警告元素。 在其他情况下,将其变为段落。
示例如下:
val descriptionTag = if (method.description.contains("DEPRECATED")) "warning" else "p" xml( """ <p>Method type: <b><font color="$font">${method.type.uppercase()}</font></b></p> <deflist> <def title="${method.summary}"> <$descriptionTag>${method.description}</$descriptionTag> </def> </deflist> """ )
全新水平的文档即代码
我们经常谈论将文档视为代码,但我们通常指的是有限数量的工具和做法,例如使用轻量级标记编写、将文档置于版本控制之下,以及使用代码审查和 linter。 但是,我们可以从开发领域吸取更多。
借助 Kotlin DSL,文档成为代码的代名词,让文档撰写人可以利用开发者常用的做法。 部分做法包括:
- 将内容的某些部分作为模块,然后将其作为许多文档集的依赖项导入,例如一些前端组件或者版权或许可协议等法律信息。
- 在编程中使用函数组合,可以将复杂的标记结构和模式分解为更简单的结构和模式,使源更加精细并且易于维护和重用。
- 将语义和前端组件视为类型,在需要的地方释放面向对象编程的优势。
可扩展性
DSL 的可扩展性将打破现有规则。 它不仅允许您添加自定义元素,还支持修改 DSL 本身,这开辟了无限可能。
您的想象力不会受到限制。 在计算机上可以实现的一切,都可以通过文档实现!
得益于与现有 JVM 库的无缝集成,您可以合并数据源、解析和丰富内容,甚至与 Selenium 和 Cucumber 等外部工具和框架集成。
Kotlin DSL 可扩展性选项示例如下:
- 解析和集成任何数据格式,包括 XML、JSON、YAML、自定义序列化格式,甚至应用程序运行时的对象。
- 添加映射并使用额外内容丰富文档。
- 使用 Readability Analysis Tool 和 Apache OpenNLP 等库处理自然语言。
- 为自动生成的部件应用测试和断言。
为什么选择 Kotlin?
先前已经有过从代码生成 HTML 的尝试,所以您可能想知道为什么我们选择 Kotlin 用于文档目的?
首先,Kotlin 具有一些高级功能,有助于创建强劲 DSL。
其次,Kotlin 以实用和对初学者友好而闻名。 它遵循简化日常任务的原则,确保新手能够快速轻松地掌握语言。
例如,在 Kotlin 中编写基本的“Hello, World!” 程序时,初学者不会被迫使用不理解的概念和关键字。
以下示例比较了 Java 与 Kotlin 中的“Hello, World!”程序:
Java:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }
Kotlin:
fun main() = println("Hello, World!")
在 Kotlin 中,您不需要定义类或使用 public static void 签名。 main() 函数作为入口点,println() 可以直接用于输出所需消息。 这种简单性是 Kotlin 的主要优势之一,使编写基本程序更为轻松愉快。
如前所述,Kotlin 与 JVM 生态系统无缝集成。 Java 已诞生接近 30 周年,具有大量实用工具和库。 在构建脚本中添加一行,即可将这些工具合并到工作流中。
选择 Kotlin,我们优先考虑在简单性和强劲功能之间取得平衡的语言,确保愉快高效的开发者体验。
我需要成为程序员才能使用 Kotlin DSL 吗?
我们经常听到文档撰写人说:“我只是一个普通的技术文档撰写人,不是开发者也不是特别精通技术! 我该怎么用它? 我需要什么编程水平才能从中受益?”
要开始使用 DSL 元素作为标记,您不需要任何编码技能,也不需要了解 DSL 的运作方式。
只有在某些自动化相关任务上,您才需要对 Kotlin 有基本的了解。 JetBrains Academy 的 Kotlin Core 课程提供了所有必备知识。
但是,我们相信,学习 Kotlin DSL 从长远来看很有价值。 凭借其直观的语法和 IDE 支持,文档撰写人可以快速精通并更充分地利用强劲的文档工具。
将这种方式合并到文档工作流时,您可能需要学习一些编程知识。 将 Kotlin DSL 集成到工作中,您可以动手学习专门适用于文档职责的编程。 毕竟,技术文档撰写人可能会更喜欢文档相关任务,而不是假设课程的分数计算或基本计算器构建等综合练习。 此外,学习 Kotlin 还有助于理解其他语言和生态系统。
这种方式不一定适合所有技术文档撰写人,但对于撰写开发者工具内容的人员来说,这会非常有助于提升技能。
结论
适用于文档的 Kotlin DSL 引入了范式转变,使技术文档撰写人能够利用编程语言的强大功能轻松创作精彩内容。 利用 Kotlin 的优势、IDE 支持以及 DSL 固有的可扩展性,文档不再只是页面上的文字。 它成为开发流程中动态、集成的部分,增强协作并提供卓越结果。
快来为您的文档需求探索 Kotlin DSL 的无限可能吧!
🚀 我们已经创建了一个示例项目,供您下载试用 Kotlin DSL。 如果您有任何疑问,请加入我们的 Slack,我们的专属频道是 #kotlin-dsl-for-docs。
拥抱代码的力量,将您的文档提升到全新高度。
祝您写作和编码快乐!
本博文英文原作者: