跳到主要内容

短代码

短代码(Shortcodes)是在 Markdown 内容中插入复杂内容的方式。本章将介绍如何使用和创建短代码。

什么是短代码?

Markdown 格式虽然简洁,但有些功能无法直接实现,比如嵌入视频、图片画廊、代码高亮等。短代码允许你在 Markdown 中插入这些复杂功能,同时保持内容的可读性。

短代码的基本语法:

<!-- 无参数 -->
{{< shortcode >}}

<!-- 有参数 -->
{{< shortcode param1="value1" param2="value2" >}}

<!-- 包含内容 -->
{{< shortcode >}}
内部内容
{{< /shortcode >}}

内置短代码

Hugo 提供了一些常用的内置短代码。

figure - 图片

{{< figure src="/images/photo.jpg" title="图片标题" alt="图片描述" >}}

完整参数:

{{< figure 
src="/images/photo.jpg"
link="https://example.com"
target="_blank"
title="点击查看大图"
alt="风景照片"
caption="这是图片说明"
attr="作者"
attrlink="https://example.com/author"
width="600px"
height="400px"
class="my-image"
>}}

youtube - YouTube 视频

{{< youtube id="VIDEO_ID" >}}

<!-- 或直接使用 URL -->
{{< youtube https://www.youtube.com/watch?v=VIDEO_ID >}}

<!-- 带参数 -->
{{< youtube id="VIDEO_ID" autoplay="true" start="30" >}}

vimeo - Vimeo 视频

{{< vimeo id="VIDEO_ID" >}}

gist - GitHub Gist

<!-- 整个 Gist -->
{{< gist username gist_id >}}

<!-- 特定文件 -->
{{< gist username gist_id filename.py >}}

instagram - Instagram 嵌入

{{< instagram POST_ID >}}

twitter - Twitter 嵌入

{{< twitter user="username" id="TWEET_ID" >}}

highlight - 代码高亮

{{< highlight python "linenos=table,hl_lines=2 3" >}}
def hello():
print("Hello, Hugo!")
return True
{{< /highlight >}}

参数说明:

  • linenos=table:显示行号(表格形式)
  • linenos=inline:显示行号(内联形式)
  • hl_lines="2 3":高亮第 2、3 行

code - 代码文件

{{< code file="main.py" lang="python" >}}
def main():
print("Hello")
{{< /code >}}

ref 和 relref - 页面引用

<!-- 绝对 URL -->
[关于页面]({{< ref "about.md" >}})

<!-- 相对 URL -->
[关于页面]({{< relref "about.md" >}})

<!-- 引用特定章节 -->
[章节]({{< relref "posts/my-post#introduction" >}})

创建自定义短代码

自定义短代码放在 layouts/shortcodes/ 目录下。

简单短代码

创建一个简单的提示框短代码:

layouts/shortcodes/note.html

<div class="note">
<strong>注意:</strong> {{ .Inner }}
</div>

使用:

{{< note >}}这是一个重要提示{{< /note >}}

带参数的短代码

创建一个带类型参数的提示框:

layouts/shortcodes/alert.html

{{ $type := .Get "type" | default "info" }}
{{ $title := .Get "title" | default "" }}

<div class="alert alert-{{ $type }}">
{{ with $title }}
<div class="alert-title">{{ . }}</div>
{{ end }}
<div class="alert-content">
{{ .Inner | markdownify }}
</div>
</div>

使用:

{{< alert type="warning" title="警告" >}}
这是一条警告信息,支持 **Markdown** 格式。
{{< /alert >}}

{{< alert type="success" >}}
操作成功完成!
{{< /alert >}}

获取参数的方式

<!-- 获取位置参数 -->
{{ .Get 0 }} <!-- 第一个参数 -->
{{ .Get 1 }} <!-- 第二个参数 -->

<!-- 获取命名参数 -->
{{ .Get "title" }}
{{ .Get "class" }}

<!-- 使用默认值 -->
{{ .Get "type" | default "info" }}

<!-- 检查参数是否存在 -->
{{ if .Get "image" }}
<img src="{{ .Get "image" }}">
{{ end }}

处理内部内容

<!-- 原样输出 -->
{{ .Inner }}

<!-- 解析 Markdown -->
{{ .Inner | markdownify }}

<!-- 转义 HTML -->
{{ .Inner | plainify }}

无闭合标签的短代码

创建图片画廊短代码:

layouts/shortcodes/gallery.html

{{ $images := .Get "images" }}
{{ $class := .Get "class" | default "gallery" }}

<div class="{{ $class }}">
{{ range split $images "," }}
{{ $img := trim . " " }}
<figure>
<img src="{{ $img }}" alt="">
</figure>
{{ end }}
</div>

使用:

{{< gallery images="/img/1.jpg, /img/2.jpg, /img/3.jpg" class="my-gallery" >}}

实用短代码示例

代码演示

创建一个带标题和说明的代码块:

layouts/shortcodes/codedemo.html

{{ $lang := .Get "lang" | default "text" }}
{{ $title := .Get "title" | default "代码示例" }}
{{ $desc := .Get "desc" }}

<div class="code-demo">
<div class="code-header">
<span class="code-title">{{ $title }}</span>
{{ with $desc }}
<span class="code-desc">{{ . }}</span>
{{ end }}
</div>
<div class="code-content">
{{ highlight .Inner $lang "" }}
</div>
</div>

使用:

{{< codedemo lang="python" title="Hello World" desc="简单的打印示例" >}}
print("Hello, World!")
{{< /codedemo >}}

折叠内容

创建可折叠的内容区域:

layouts/shortcodes/collapse.html

{{ $title := .Get "title" | default "点击展开" }}
{{ $open := .Get "open" | default false }}

<details {{ if $open }}open{{ end }}>
<summary>{{ $title }}</summary>
<div class="collapse-content">
{{ .Inner | markdownify }}
</div>
</details>

使用:

{{< collapse title="查看详细说明" >}}
这里是详细说明内容,支持 **Markdown** 格式。
{{< /collapse >}}

外部链接

创建带图标的链接:

layouts/shortcodes/extlink.html

{{ $url := .Get 0 }}
{{ $text := .Get 1 | default $url }}

<a href="{{ $url }}" target="_blank" rel="noopener noreferrer" class="external-link">
{{ $text }}
<svg class="icon" viewBox="0 0 24 24">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</svg>
</a>

使用:

{{< extlink "https://gohugo.io" "Hugo 官网" >}}

图片对比

创建并排对比的图片展示:

layouts/shortcodes/compare.html

{{ $before := .Get "before" }}
{{ $after := .Get "after" }}
{{ $beforeLabel := .Get "beforeLabel" | default "之前" }}
{{ $afterLabel := .Get "afterLabel" | default "之后" }}

<div class="image-compare">
<div class="compare-item">
<img src="{{ $before }}" alt="{{ $beforeLabel }}">
<span class="label">{{ $beforeLabel }}</span>
</div>
<div class="compare-item">
<img src="{{ $after }}" alt="{{ $afterLabel }}">
<span class="label">{{ $afterLabel }}</span>
</div>
</div>

使用:

{{< compare before="/img/before.jpg" after="/img/after.jpg" beforeLabel="优化前" afterLabel="优化后" >}}

视频嵌入

创建通用的视频嵌入短代码:

layouts/shortcodes/video.html

{{ $src := .Get "src" }}
{{ $type := .Get "type" | default "video/mp4" }}
{{ $poster := .Get "poster" }}
{{ $width := .Get "width" | default "100%" }}
{{ $controls := .Get "controls" | default true }}
{{ $autoplay := .Get "autoplay" | default false }}
{{ $loop := .Get "loop" | default false }}

<video
width="{{ $width }}"
{{ if $poster }}poster="{{ $poster }}"{{ end }}
{{ if $controls }}controls{{ end }}
{{ if $autoplay }}autoplay{{ end }}
{{ if $loop }}loop{{ end }}
>
<source src="{{ $src }}" type="{{ $type }}">
您的浏览器不支持视频播放。
</video>

使用:

{{< video src="/videos/demo.mp4" poster="/img/poster.jpg" controls="true" >}}

卡片组件

创建信息卡片:

layouts/shortcodes/card.html

{{ $title := .Get "title" }}
{{ $image := .Get "image" }}
{{ $link := .Get "link" }}
{{ $class := .Get "class" | default "" }}

<div class="card {{ $class }}">
{{ with $image }}
<div class="card-image">
<img src="{{ . }}" alt="{{ $title }}">
</div>
{{ end }}
<div class="card-content">
{{ with $title }}
<h3 class="card-title">{{ . }}</h3>
{{ end }}
<div class="card-body">
{{ .Inner | markdownify }}
</div>
{{ with $link }}
<a href="{{ . }}" class="card-link">了解更多</a>
{{ end }}
</div>
</div>

使用:

{{< card title="Hugo" image="/img/hugo-logo.png" link="https://gohugo.io" >}}
Hugo 是世界上最快的静态网站生成器。
{{< /card >}}

短代码最佳实践

命名规范

使用小写字母和连字符:

layouts/shortcodes/
├── alert.html
├── code-demo.html
├── image-gallery.html
└── video-player.html

参数验证

检查必需参数:

{{ if not (.Get "src") }}
{{ errorf "shortcode 'video' requires 'src' parameter" }}
{{ end }}

提供默认值

{{ $width := .Get "width" | default "100%" }}
{{ $class := .Get "class" | default "default-class" }}

支持 Markdown

内部内容通常应该支持 Markdown:

{{ .Inner | markdownify }}

添加 CSS 类

允许用户自定义样式:

<div class="shortcode-name {{ .Get "class" }}">
...
</div>

短代码与 Markdown 渲染

两种语法

<!-- 使用 {{< >}}:内部内容不渲染 Markdown -->
{{< highlight html >}}
**这是粗体**(不会被渲染)
{{< /highlight >}}

<!-- 使用 {{% %}}:内部内容渲染 Markdown -->
{{% note %}}
**这是粗体**(会被渲染为粗体)
{{% /note %}}

选择建议

  • 纯 HTML 输出:使用 {{< >}}
  • 需要 Markdown 渲染:使用 {{% %}}

小结

本章介绍了 Hugo 短代码的核心知识:

  1. 内置短代码提供了常用的嵌入功能
  2. 自定义短代码可以扩展 Markdown 功能
  3. 短代码支持参数和内部内容
  4. 使用 markdownify 处理 Markdown 内容
  5. 合理使用短代码可以保持内容的简洁性

下一章将学习 Hugo 的配置系统。