Callouts 是 Obsidian 中增强显示的工具,丰富了原始 Markdown 中具备的标签。
本文主要介绍如何将 Callouts 移植到 Hugo 中,使得本地 Obsidian 预览结果和 Hugo 渲染出来的 Callouts Block 具备一致的效果.
Todo
- 增加可折叠
- 修复嵌套时样式被覆盖
在 Obsidian 中 使用 Callouts 的如下,其支持除了 info 以外的其他很多类型
> [!info]
> Here's a callout block.
其主要支持的特性有可替换标题, 可嵌套, 可折叠。
> [!tip] Title-only callout
> [!faq]- Are callouts foldable?
> Yes! In a foldable callout, the contents are hidden when the callout is collapsed.
> [!question] Can callouts be nested?
> > [!todo] Yes!, they can.
> > > [!example] You can even use multiple layers of nesting.
Hugo 使用默认的渲染器 goldmark.renderer
将上述 Callouts 转换为:
<blockquote>
<p>[!tip] Title-only callout</p>
</blockquote>
<blockquote>
<p>[!faq]- Are callouts foldable?
Yes! In a foldable callout, the contents are hidden when the callout is collapsed.</p>
</blockquote>
<blockquote>
<p>[!question] Can callouts be nested?</p>
<blockquote>
<p>[!todo] Yes!, they can.</p>
<blockquote>
<p>[!example] You can even use multiple layers of nesting.</p>
</blockquote>
</blockquote>
</blockquote>
上述例子中可以发现:
blockquote
不是每一行都单独使用一个<p>
标签,这个可以通过在这一行后加入两个空格强制让其为下一行增加<p>
标签 1blockquote
原生支持嵌套语法,不需要做调整
因此,我们主要需要关注前两个 Callouts 的移植,其在 Obsidian 渲染出来的结果如下:
<div data-callout-metadata="" data-callout-fold="" data-callout="tip" class="callout">
<div class="callout-title" dir="auto">
<div class="callout-icon"><svg ..></svg></div>
<div class="callout-title-inner">Title-only callout</div>
</div>
</div>
<div data-callout-metadata="" data-callout-fold="-" data-callout="faq" class="callout is-collapsible">
<div class="callout-title" dir="auto">
<div class="callout-icon"><svg ..></svg></div>
<div class="callout-title-inner">Are callouts foldable?</div>
<div class="callout-fold"><svg ..></svg></div>
</div>
<div class="callout-content" style="">
<p dir="auto">Yes! In a foldable callout, the contents are hidden when collapsed.</p>
</div>
</div>
由于找到对应的结尾标签比较困难,因此直接考虑在 blockquote
上改变。
在 layouts/partials/obsidian.md
中定义 obsidian
函数进行转义2:
{{- define "partials/obsidian.html" -}}
{{- $content := .content -}}
{{- $pageRelLink := .pageRelLink -}}
{{- $regexCallout := `<blockquote>\n<p>\[!(.+)\](-?) (.+)?\<` -}}
{{- $callouts := $content | findRE $regexCallout -}}
{{- /* Convert Callouts */ -}}
{{- range $callouts -}}
{{- $callout := findRESubmatch $regexCallout . -}}
{{- $type := index $callout 0 1 -}}
{{- $isFold := index $callout 0 2 -}}
{{- $title := index $callout 0 3 -}}
{{- $content = replaceRE $regexCallout `<blockquote class="callout" data-callout="$1" callout-fold="$2"><p><div class="title">$3</div><` $content 1 -}}
{{- end -}}
{{- /* Output content */ -}}
{{- $content | safeHTML -}}
{{- end -}}
这样,通过增加了 data-callout
字段可以进行不同类型 Callout 的区分,并且转义的过程中不动不容易正则匹配的反括号,避免过于复杂的逻辑。
在 layouts/_default/single.html
中将 {{.Content}}
替换为 {{- partial "partials/obsidian.html" (dict "content" .Content "pageRelLink" .Page.RelPermalink) -}}
使我们的函数进行转义。
效果:
Title-only callout
[!faq]- Are callouts foldable? Yes! In a foldable callout, the contents are hidden when the callout is collapsed.
Can callouts be nested?Yes!, they can.You can even use multiple layers of nesting.
Last modified on 2024-08-07