语法高亮

AsciiDoc 定义了一种名为源代码块的列表块样式,用于将旨在通过语法高亮器着色的源代码片段添加到文档中。以下是一个源代码块的简单示例。

[source,ruby]
----
puts "Hello, World!"
----

如果在一个列表块上指定了语言,则源代码样式是隐含的。因此,在这种情况下可以省略它。

[,ruby]
----
puts "Hello, World!"
----

这是我们期望的显示效果。

puts "Hello, World!"

由 Asciidoctor 等 Asciidoctor 处理器负责将语法高亮应用于此源代码块,这一过程称为源代码高亮。Asciidoctor 提供适配器,这些适配器可以与多个流行的语法高亮库集成以执行此任务。它还提供了一个接口,用于实现自定义语法高亮适配器。

语法高亮器类型

Asciidoctor 支持两种类型的语法高亮器:客户端和构建时。让我们分别探讨这两种类型及其工作原理。

一个客户端语法高亮器在页面加载时在浏览器中执行语法高亮。Asciidoctor 本身不调用语法高亮器。相反,它专注于将资源添加到生成的 HTML 中,以便浏览器可以加载语法高亮器并运行它。对于这种类型的语法高亮器,Asciidoctor 会按原样将源代码块的内容传递到输出。它还会向元素添加元数据,以便语法高亮器知道要高亮它以及它是哪种语言。不幸的是,在这种情况下,Asciidoctor 不会处理源代码块中的标注编号,因此它们可能会导致语法高亮器出错。

一个构建时语法高亮器在 AsciiDoc 转换期间执行语法高亮。在这种情况下,Asciidoctor 会调用语法高亮器。它还会负责隐藏语法高亮器中的标注编号,确保它们在之后放回正确的位置。Asciidoctor 在输出中发出的是语法高亮器产生的resul,即包含在<span>元素中的标记,用于应用颜色和其他格式(内联或通过 CSS 类)。这些语法高亮器倾向于支持更多功能,因为 Asciidoctor 对过程有更大的控制权。

客户端 vs 构建时

每种类型都有优点和缺点。客户端语法高亮器的优点是它不需要安装任何额外的库。它还可以加快转换速度,并产生更小的输出,因为语法高亮被推迟到页面加载。主要缺点是源代码块中的标注可能会被语法高亮器弄乱或使其混淆。构建时语法高亮器的优点是您可以更好地控制语法高亮,并且可以启用其他功能,例如行号和行高亮。主要缺点是需要安装额外的库,它会减慢转换速度,并导致输出变大。

您应该尝试每种语法高亮器,找到最适合您的那一种。

内置语法高亮器适配器

类型 语法高亮器 所需 Gem 兼容的转换器

客户端

Highlight.js

不适用

HTML, Reveal.js

构建时

CodeRay

coderay (>= 1.1)

HTML, PDF, EPUB3, Reveal.js

Pygments

pygments.rb (>= 1.2)

HTML, PDF, EPUB3, Reveal.js

Rouge

rouge (>= 2)

HTML, PDF, EPUB3, Reveal.js

Asciidoctor 在生成 DocBook 时不应用语法高亮。假设这是 DocBook 工具链可以处理的任务。DocBook 转换器为源代码块生成一个<programlisting>元素,并将指定的源代码语言传递给 AsciiDoc。然后由 DocBook 工具链负责将语法高亮应用于该标签的内容。

您可以在Highlight.jsRougePygmentsCodeRay页面上深入了解这些集成。

您还可以通过创建自定义语法高亮器适配器来创建自己的集成。

源代码块上的自定义替换

您不应该将语法高亮与 AsciiDoc 文本格式化(即quotesmacros替换)混合使用。在许多转换器中,这两个操作是互斥的。

示例 1. 在源代码块上不当使用自定义替换
[,java,subs=+quotes]
----
interface OrderRepository extends CrudRepository<Order,Long> {

  *List<Order>* findByCategory(String category);

  Order findById(long id);
}
----

AsciiDoc 文本格式化引入的额外标记可能会使语法高亮器混淆并导致意外结果。虽然它可能在 HTML 后端的某些语法高亮器中起作用(也许它们知道如何处理格式化标签),但在转换为 PDF 等其他格式时,它几乎肯定会失败。

如果您打算使用subs属性来自定义源代码块上的替换,则应将这些替换限制为属性替换(attributes)。

示例 2. 在源代码块上有效使用自定义替换
[,java,subs=attributes+]
----
interface {model}Repository extends CrudRepository<{model},Long> {

  {model} findById(long id);
}
----

如果您仍然需要强调代码块中的某些标记,您应该通过创建自定义的词法分析器或格式化程序来做到这一点,该格式化程序能够理解这些额外的语义,甚至可能是提示。换句话说,通过语法高亮器进行工作,使其在突出显示过程中添加,使语法高亮器完全了解正在发生的事情。另一种选择是使用自定义语法高亮器适配器

在尝试让语法高亮器识别新标记之前,请确保它尚未识别它们。如果它已经识别了,那么可能只是定制语法高亮器主题以对这些标记应用不同的格式。