代码块
创建代码块渲染钩子,覆盖围栏代码块的默认高亮输出,并按语言定制渲染方式。
Markdown 中的代码块
下面这段 Markdown 含有一个围栏代码块:
```sh {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
declare a=1
echo "$a"
exit
```一个围栏代码块由以下部分组成:
- 起始代码围栏
- 可选的信息字符串
- 代码样例
- 结束代码围栏
在上面的例子中,信息字符串包含:
- 代码样例的语言(第一个词)
- 可选的属性列表,用空格或逗号分隔,写在花括号内
信息字符串中的属性可以是通用属性,也可以是高亮选项。
上例中的通用属性是 class 与 id。如果代码块渲染钩子没有做特殊处理,Hugo 会把每个通用属性加到包裹代码块输出的 HTML 元素上。按照自身的内容安全模型,Hugo 会移除 onclick、onmouseover 这类 HTML 事件属性。通用属性通常是全局 HTML 属性,也可以包含自定义属性。
上例中的高亮选项是 lineNos 与 tabWidth。Hugo 使用内建语法高亮器渲染代码样例,可以通过指定一个或多个高亮选项来控制渲染结果的外观。
上下文
代码块渲染钩子模板接收以下上下文:
Attributes- (
map)信息字符串中的通用属性。 Inner- (
string)起始与结束代码围栏之间的内容,不含信息字符串。 Options- (
map)信息字符串中的高亮选项。 Ordinal- (
int)代码块在页面中的序号,从 0 开始。 Page- (
page)当前页面的引用。 PageInner- (
page)通过RenderShortcodes方法嵌套的页面的引用。详见下文 PageInner details。 Position- (
text.Position)代码块在页面内容中的位置。 Type- (
string)信息字符串的第一个词,通常是代码语言。
示例
默认情况下,Hugo 使用内建语法高亮器渲染围栏代码块,并包裹渲染结果。要写出行为一致的渲染钩子:
{{ $result := transform.HighlightCodeBlock . }}
{{ $result.Wrapped }}当语言未指定或高亮器不支持该语言时回退为纯文本:
{{- $opts := dict }}
{{- if not (transform.CanHighlight .Type) }}
{{- $opts = dict "type" "text" }}
{{- end }}
{{- $result := transform.HighlightCodeBlock . $opts }}
{{- $result.Wrapped }}尽管可以用一个模板加条件逻辑来按语言区分行为,也可以为不同语言创建单独的模板:
layouts/
└── _markup/
├── render-codeblock-mermaid.html
├── render-codeblock-python.html
└── render-codeblock.html例如,创建一个渲染 Mermaid 图表的代码块渲染钩子:
<pre class="mermaid">
{{ .Inner | htmlEscape | safeHTML }}
</pre>
{{ .Page.Store.Set "hasMermaid" true }}然后在基础模板的末尾、body 结束标签之前加入这段代码:
{{ if .Store.Get "hasMermaid" }}
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
{{ end }}内建钩子
Hugo 自带一个内建代码块渲染钩子,用于渲染 GoAT 图表(ASCII 图),详见图表。
PageInner details
PageInner 的主要用途是相对于被包含的页面来解析链接与页面资源。例如可以创建一个「包含」短代码,用多个内容文件拼装一个页面,同时为脚注与目录保留全局上下文:先用位置参数取出要包含的页面逻辑路径,再调用该页面的 RenderShortcodes 方法,取不到页面时用 errorf 报错。
然后在 Markdown 中用 Markdown 记法调用这个短代码,被包含页面的路径写在位置参数里。渲染 /posts/post-2 时触发的任何渲染钩子,调用 Page 会得到 /posts/post-1,调用 PageInner 则会得到 /posts/post-2。
PageInner 在不适用时会回退为 Page 的值,并且始终有返回值。它只对调用 RenderShortcodes 方法的短代码有意义,并且必须以 Markdown 记法调用该短代码。