AsciiDoc 定义了一种称为 source block 的列表块样式,用于向文档添加打算由语法高亮器着色的源代码片段。这里是一个简单的源代码块示例:
[source,ruby]
----
puts "Hello, World!"
----
如果在代码块上指定了一种语言,那么源代码的样式就是隐含的。因此,在这种情况下,它可以被排除。
[,ruby]
----
puts "Hello, World!"
----
我们期望它这样出现:
puts "Hello, World!"
由AsciiDoc处理器,例如Asciidoctor,负责将语法高亮应用到这个源代码块上,这个过程称为源代码高亮(source highlighting)。Asciidoctor提供了适配器,与多个流行的语法高亮库集成以执行这项任务。它还提供了一个接口用于实现自定义的语法高亮适配器。
语法高亮器类型
Asciidoctor 支持两种类型的语法高亮器:客户端和构建时。让我们探索每种类型以及它们的工作方式。
一种[术语]客户端语法高亮器*在浏览器中执行语法高亮,随着页面的加载。Asciidoctor不会自己调用语法高亮器。相反,它专注于向生成的HTML中添加资源,以便浏览器可以加载语法高亮器并运行它。对于这类型的语法高亮器,Asciidoctor将源代码块的内容按原样传递到输出中。它还会向元素添加元数据,以便语法高亮器知道对它进行高亮以及它是哪种语言。不幸的是,Asciidoctor在这种情况下不会处理源代码块中的标注数字,所以它们可能会导致语法高亮器出现错误。
一种[术语]构建时语法高亮器* 在AsciiDoc转换期间执行语法高亮显示。Asciidoctor在这种情况下会调用语法高亮器。它还负责从语法高亮器中隐藏标注(callout)数字,确保它们在之后能被放回正确的位置。Asciidoctor输出的结果是语法高亮器产生的结果,这些结果是用`<span>`元素包围的词法标记,以应用颜色和其他格式化效果(无论是内联的还是通过CSS类)。这些语法高亮器倾向于支持更多的特性,因为Asciidoctor对整个过程有更大的控制权。
客户端与构建时
每种类型都有其优点和缺点。客户端语法高亮的优点是不需要安装任何额外的库。它也使得转换更快,并且因为语法高亮是推迟到页面加载时再进行,所以产生的输出更小。主要缺点是源代码块中的标注可能会被语法高亮器弄乱或令其混淆。在构建时使用语法高亮器的好处是你可以对语法高亮有更多的控制,并且可以启用额外的特性,比如行号和行高亮。主要的缺点是它需要安装一个额外的库,会减慢转换速度,并且导致输出文件变大。
你应该尝试每种语法高亮工具,并找到最适合你的那一个。
内置的语法高亮适配器
Type | Syntax Highlighter | Required Gem | Compatible Converters |
---|---|---|---|
Client-side |
Highlight.js |
n/a |
HTML, Reveal.js |
Build-time |
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工具链来对该标签内容应用语法高亮。
你可以在highlightjs.html、rouge.html、pygments.html 和 coderay.html 页面深入探索这些集成。
你也可以通过创建一个custom.html来实现你自己的集成。
给源代码块自定义订阅
你不应该将语法高亮与AsciiDoc文本格式(即,quotes
和 macros
替换)混合在一起。在许多转换器中,这两种操作是互斥的。
[,java,subs=+quotes]
----
interface OrderRepository extends CrudRepository<Order,Long> {
*List<Order>* findByCategory(String category);
Order findById(long id);
}
----
AsciiDoc文本格式化引入的额外标记可能会混淆语法高亮器,并导致出现意外结果。虽然这可能在一些HTML后端的语法高亮器中工作得很好(也许它们知道如何处理这些格式化标签),但在转换为PDF等其他格式时,几乎可以肯定会失败。
如果你打算使用`subs`属性对源代码块进行自定义替换,你应该将这些替换限制为属性替换(attributes
)。
[,java,subs=attributes+]
----
interface {model}Repository extends CrudRepository<{model},Long> {
{model} findById(long id);
}
----
如果您仍然需要在代码块中强调特定的标记,您应该通过为语法高亮库创建一个自定义的词法分析器或格式化程序来完成,这样它就能理解这些附加的语义,并可能甚至能提供一些提示。换句话说,应该通过语法高亮器来完成这个过程,这样就能在高亮过程中添加它,让语法高亮器完全知道正在发生什么。另一个选项是使用一个自定义语法高亮器适配器。
在尝试让语法高亮器识别新的标记前,请确保它之前没有识别它们。如果已经可以识别,那么可能只需要通过自定义语法高亮器的主题来对那些标记应用不同的格式设置。