Hugo 短代码模板
介绍
Hugo 为许多常见任务提供 嵌入式短代码,但您可能需要为更具体的需求创建自己的短代码。您可能开发的一些自定义短代码示例包括:
- 音频播放器
- 视频播放器
- 图像画廊
- 图表
- 地图
- 表格
- 以及许多其他自定义元素
目录结构
在 layouts/_shortcodes 目录中创建 短代码 模板,可以在其根目录或组织到子目录中。
layouts/
└── _shortcodes/
├── diagrams/
│ ├── kroki.html
│ └── plotly.html
├── media/
│ ├── audio.html
│ ├── gallery.html
│ └── video.html
├── capture.html
├── column.html
├── include.html
└── row.html在子目录中调用短代码时,指定其相对于 _shortcode 目录的路径,不包括文件扩展名。
{{< media/audio path=/audio/podcast/episode-42.mp3 >}}查找顺序
Hugo 根据短代码名称、当前输出格式和当前语言选择 短代码 模板。下面的示例按特异性降序排序。最不具体的路径在列表底部。
| 短代码名称 | 输出格式 | 语言 | 模板路径 |
|---|---|---|---|
| foo | html | en | layouts/_shortcodes/foo.en.html |
| foo | html | en | layouts/_shortcodes/foo.html.html |
| foo | html | en | layouts/_shortcodes/foo.html |
| foo | html | en | layouts/_shortcodes/foo.html.en.html |
| 短代码名称 | 输出格式 | 语言 | 模板路径 |
|---|---|---|---|
| foo | rss | en | layouts/_shortcodes/foo.en.rss.xml |
| foo | rss | en | layouts/_shortcodes/foo.rss.xml |
| foo | rss | en | layouts/_shortcodes/foo.en.xml |
| foo | rss | en | layouts/_shortcodes/foo.xml |
方法
在您的 短代码 模板中使用这些方法。请参阅每个方法的文档以获取详细信息和示例。
- Get
- 返回给定参数的值。
- Inner
- 返回 shortcode 开始和结束标签之间的内容,适用于 shortcode 调用包含结束标签的情况。
- InnerDeindent
- 返回 shortcode 开始和结束标签之间的内容,并移除缩进,适用于 shortcode 调用包含结束标签的情况。
- IsNamedParams
- 报告 shortcode 调用是否使用命名参数。
- Name
- 返回 shortcode 文件名,不包括文件扩展名。
- Ordinal
- 返回 shortcode 相对于其父级的从零开始的序号。
- Page
- 返回调用 shortcode 的页面对象。
- Params
- 返回 shortcode 参数的集合。
- Parent
- 在嵌套 shortcode 中返回父 shortcode 上下文。
- Position
- 返回调用 shortcode 的文件名和位置。
- Ref
- 返回具有给定路径、语言和输出格式的页面的绝对 URL。
- RelRef
- 返回具有给定路径、语言和输出格式的页面的相对 URL。
- Scratch
- 返回一个"暂存板"来存储和操作数据,作用域为当前 shortcode。
- Site
- 返回站点对象。
- Store
- 返回一个"暂存板"来存储和操作数据,作用域为当前 shortcode。
示例
这些示例的复杂度从简单到中等高级,有些为清晰起见进行了简化。
插入年份
创建短代码以插入当前年份:
{{- now.Format "2006" -}}然后在标记内调用短代码:
这是 {{< year >}},看看我们走了多远。此短代码可以内联使用或作为块单独使用。如果短代码可能内联使用,请使用带连字符的 模板动作 分隔符删除周围的 空白。
插入图像
此示例假设以下内容结构,其中 content/example/index.md 是包含一个或多个 页面资源 的 页面捆绑。
content/
├── example/
│ ├── a.jpg
│ └── index.md
└── _index.md创建短代码以捕获图像作为页面资源,将其调整为给定宽度,转换为 WebP 格式,并添加 alt 属性:
{{- with .Page.Resources.Get (.Get "path") }}
{{- with .Process (printf "resize %dx wepb" ($.Get "width")) -}}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ $.Get "alt" }}">
{{- end }}
{{- end -}}然后在标记内调用短代码:
{{< image path=a.jpg width=300 alt="一只白色的小猫" >}}上面的示例使用了:
确保您彻底理解上下文的概念。新手用户最常见的模板错误与上下文有关。
在 模板入门介绍 中阅读有关上下文的更多信息。
插入图像并处理错误
前面的示例虽然功能齐全,但如果图像缺失则静默失败,并且在缺少必需参数时不会优雅地退出。我们将添加错误处理来解决这些问题:
{{- with .Get "path" }}
{{- with $r := $.Page.Resources.Get ($.Get "path") }}
{{- with $.Get "width" }}
{{- with $r.Process (printf "resize %dx wepb" ($.Get "width" )) }}
{{- $alt := or ($.Get "alt") "" -}}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ $alt }}">
{{- end }}
{{- else }}
{{- errorf "短代码 %q 需要 'width' 参数:见 %s" $.Name $.Position }}
{{- end }}
{{- else }}
{{- warnf "短代码 %q 无法找到 %s:见 %s" $.Name ($.Get "path") $.Position }}
{{- end }}
{{- else }}
{{- errorf "短代码 %q 需要 'path' 参数:见 %s" .Name .Position }}
{{- end -}}如果作者疏忽了提供 path 或 width 参数,此模板将抛出错误并优雅地失败构建,如果在指定路径找不到图像,则发出警告。如果作者未提供 alt 参数,则 alt 属性设置为空字符串。
Name 和 Position 方法为错误和警告提供有用的上下文。例如,缺少 width 参数会导致短代码抛出此错误:
ERROR 短代码 "image" 需要 'width' 参数:见 "/home/user/project/content/example/index.md:7:1"位置参数
短代码参数可以 命名或位置。我们之前使用了命名参数;让我们探索位置参数。这是我们示例的命名参数版本:
{{< image path=a.jpg width=300 alt="一只白色的小猫" >}}这是使用位置参数调用它的方式:
{{< image a.jpg 300 "一只白色的小猫" >}}使用从零开始的键的 Get 方法,我们将在模板中初始化具有描述性名称的变量:
{{ $path := .Get 0 }}
{{ $width := .Get 1 }}
{{ $alt := .Get 2 }}位置参数适用于经常使用且有一到两个参数的短代码。由于您会经常使用它们,参数顺序将很容易记住。对于不经常使用的短代码,或那些有两个以上参数的短代码,命名参数提高了可读性并减少了错误机会。
命名和位置参数
您可以创建同时接受命名和位置参数的短代码,但不能同时使用。使用 IsNamedParams 方法确定短代码调用是使用命名还是位置参数:
{{ $path := cond (.IsNamedParams) (.Get "path") (.Get 0) }}
{{ $width := cond (.IsNamedParams) (.Get "width") (.Get 1) }}
{{ $alt := cond (.IsNamedParams) (.Get "alt") (.Get 2) }}此示例使用 cond 作为 compare.Conditional 函数的别名,如果 IsNamedParams 返回 true 则按名称获取参数,否则按位置获取参数。
参数集合
使用 Params 方法将参数作为集合访问。
使用命名参数时,Params 方法返回映射:
{{< image path=a.jpg width=300 alt="一只白色的小猫" >}}{{ .Params.path }} → a.jpg
{{ .Params.width }} → 300
{{ .Params.alt }} → 一只白色的小猫使用位置参数时,Params 方法返回切片:
{{< image a.jpg 300 "一只白色的小猫" >}}{{ index .Params 0 }} → a.jpg
{{ index .Params 1 }} → 300
{{ index .Params 2 }} → 一只白色的小猫将 Params 方法与 collections.IsSet 函数结合使用以确定是否设置了参数,即使其值是假值。
内部内容
使用 Inner 方法提取短代码标签内包含的内容。此示例演示如何将内容和标题传递给短代码。然后短代码生成包含 h2 元素(显示标题)和所提供内容的 div 元素。
{{< contrived title="一个虚构的示例" >}}
这是一个 **粗体** 词,这是一个 _强调_ 词。
{{< /contrived >}}<div class="contrived">
<h2>{{ .Get "title" }}</h2>
{{ .Inner | .Page.RenderString }}
</div>前面的示例使用 标准表示法 调用短代码,需要我们使用 RenderString 方法处理内部内容以将 Markdown 转换为 HTML。当使用 Markdown 表示法 调用短代码时,不需要此转换。
嵌套
Parent 方法在短代码在父短代码上下文中调用时提供对父短代码上下文的访问。这提供了一个继承模型。
以下示例是虚构的但演示了概念。假设您有一个 gallery 短代码,期望一个命名 class 参数:
<div class="{{ .Get "class" }}">
{{ .Inner }}
</div>您还有一个具有单个命名 src 参数的 img 短代码,您希望在 gallery 和其他短代码内调用它,以便父级定义每个 img 的上下文:
{{ $src := .Get "src" }}
{{ with .Parent }}
<img src="{{ $src }}" class="{{ .Get "class" }}-image">
{{ else }}
<img src="{{ $src }}">
{{ end }}然后您可以在内容中调用短代码,如下所示:
{{< gallery class="content-gallery" >}}
{{< img src="/images/one.jpg" >}}
{{< img src="/images/two.jpg" >}}
{{< /gallery >}}
{{< img src="/images/three.jpg" >}}这将输出以下 HTML。请注意前两个 img 短代码如何继承父 gallery 调用设置的 class 值 content-gallery,而第三个 img 仅使用 src:
<div class="content-gallery">
<img src="/images/one.jpg" class="content-gallery-image">
<img src="/images/two.jpg" class="content-gallery-image">
</div>
<img src="/images/three.jpg">其他示例
作为指导,请考虑检查 Hugo 的嵌入式短代码。源代码可在 GitHub 上获取,可以提供有用的模型。
检测
HasShortcode 方法允许您检查页面上是否调用了特定短代码。例如,考虑自定义音频短代码:
{{< audio src=/audio/test.mp3 >}}您可以在基础模板中使用 HasShortcode 方法,如果页面上使用了音频短代码,则有条件地加载 CSS:
<head>
...
{{ if .HasShortcode "audio" }}
<link rel="stylesheet" src="/css/audio.css">
{{ end }}
...
</head>