Hugo 速查表
本文档提供 Hugo 常用命令、配置和模板语法的快速参考。
命令行
站点命令
| 命令 | 说明 |
|---|---|
hugo new site <name> | 创建新站点 |
hugo new content <path> | 创建新内容 |
hugo new theme <name> | 创建新主题 |
构建命令
| 命令 | 说明 |
|---|---|
hugo | 构建站点 |
hugo -D | 包含草稿构建 |
hugo -F | 包含未来日期内容 |
hugo --minify | 压缩输出 |
hugo -d <dir> | 指定输出目录 |
hugo -b <url> | 指定基础 URL |
hugo --gc | 清理未使用资源 |
开发命令
| 命令 | 说明 |
|---|---|
hugo server | 启动开发服务器 |
hugo server -D | 包含草稿 |
hugo server --navigateToChanged | 自动跳转到修改的页面 |
hugo server --liveReloadPort 443 | 指定热重载端口 |
hugo server --bind 0.0.0.0 | 允许外部访问 |
其他命令
| 命令 | 说明 |
|---|---|
hugo version | 显示版本 |
hugo env | 显示环境信息 |
hugo list drafts | 列出草稿 |
hugo list future | 列出未来内容 |
hugo list expired | 列出过期内容 |
hugo config | 显示配置 |
hugo convert toYAML | 转换配置格式 |
目录结构
新模板系统(Hugo v0.146.0+):
my-site/
├── archetypes/ # 内容模板
│ └── default.md
├── assets/ # 需要处理的资源
│ ├── css/
│ └── js/
├── content/ # 内容文件
│ ├── posts/
│ └── _index.md
├── data/ # 数据文件
├── layouts/ # 模板文件
│ ├── baseof.html # 基础模板
│ ├── home.html # 首页模板
│ ├── page.html # 单页模板
│ ├── section.html # 分区列表模板
│ ├── _partials/ # 局部模板
│ ├── _shortcodes/ # 短代码
│ └── _markup/ # 渲染钩子
├── static/ # 静态文件
├── themes/ # 主题
├── public/ # 构建输出
└── hugo.toml # 配置文件
旧模板系统(v0.145 及之前):
my-site/
├── layouts/
│ ├── _default/ # 默认模板
│ ├── partials/ # 局部模板
│ └── shortcodes/ # 短代码
└── ...
Front Matter
常用变量
---
title: "文章标题"
date: 2024-01-15
lastmod: 2024-01-20
draft: false
weight: 10
description: "文章描述"
summary: "自定义摘要"
slug: "custom-url"
url: "/custom/path/"
aliases:
- /old-url/
tags: ["Hugo", "Web"]
categories: ["技术"]
image: "/images/cover.jpg"
toc: true
---
TOML 格式
+++
title = "文章标题"
date = 2024-01-15
draft = false
tags = ["Hugo", "Web"]
+++
JSON 格式
{
"title": "文章标题",
"date": "2024-01-15",
"draft": false
}
模板语法
变量
{{ .Title }} <!-- 页面标题 -->
{{ .Content }} <!-- 页面内容 -->
{{ .Summary }} <!-- 摘要 -->
{{ .Date }} <!-- 日期 -->
{{ .RelPermalink }} <!-- 相对 URL -->
{{ .Permalink }} <!-- 绝对 URL -->
{{ .Site.Title }} <!-- 站点标题 -->
{{ .Site.BaseURL }} <!-- 站点基础 URL -->
{{ .Params.custom }} <!-- 自定义参数 -->
条件判断
{{ if .Title }}{{ end }}
{{ if eq .Type "posts" }}{{ end }}
{{ if ne .Draft true }}{{ end }}
{{ if and .Title .Content }}{{ end }}
{{ if or .Params.featured .Params.pinned }}{{ end }}
{{ if not .Draft }}{{ end }}
{{ if eq .Section "posts" }}
<!-- posts section -->
{{ else if eq .Section "tutorials" }}
<!-- tutorials section -->
{{ else }}
<!-- other -->
{{ end }}
{{ with .Params.author }}
<p>作者:{{ . }}</p>
{{ end }}
循环
{{ range .Site.RegularPages }}
<h2>{{ .Title }}</h2>
{{ end }}
{{ range first 5 .Site.RegularPages }}
<h2>{{ .Title }}</h2>
{{ end }}
{{ range .Site.RegularPages.ByDate.Reverse }}
<h2>{{ .Title }}</h2>
{{ end }}
{{ range $index, $page := .Site.RegularPages }}
<div class="post-{{ $index }}">{{ $page.Title }}</div>
{{ end }}
<!-- 循环控制(Hugo 0.124+) -->
{{ range .Pages }}
{{ if .Draft }}
{{ continue }} <!-- 跳过本次迭代 -->
{{ end }}
{{ if gt .WordCount 5000 }}
{{ break }} <!-- 跳出循环 -->
{{ end }}
{{ end }}
函数
<!-- 字符串 -->
{{ .Title | upper }} <!-- 大写 -->
{{ .Title | lower }} <!-- 小写 -->
{{ .Title | title }} <!-- 标题格式 -->
{{ .Summary | truncate 100 }} <!-- 截断 -->
{{ .Title | replace "old" "new" }} <!-- 替换 -->
{{ .Title | replaceRE "pattern" "replacement" }} <!-- 正则替换 -->
{{ split "a,b,c" "," }} <!-- 分割 -->
{{ delimit .Params.tags ", " }} <!-- 连接 -->
{{ strings.Contains .Content "text" }} <!-- 包含判断 -->
{{ findRE "<h2>(.*?)</h2>" .Content }} <!-- 正则匹配 -->
<!-- 日期 -->
{{ .Date.Format "2006-01-02" }}
{{ .Date.Format "2006年01月02日" }}
{{ now }}
{{ time.AsTime "2024-01-15" }}
<!-- 数学 -->
{{ add 1 2 }} <!-- 3 加法 -->
{{ sub 5 2 }} <!-- 3 减法 -->
{{ mul 3 4 }} <!-- 12 乘法 -->
{{ div 10 2 }} <!-- 5 除法 -->
{{ mod 10 3 }} <!-- 1 取模 -->
{{ math.Max 1 5 3 }} <!-- 最大值 -->
{{ math.Min 5 3 8 }} <!-- 最小值 -->
{{ math.Pow 2 10 }} <!-- 幂运算 -->
{{ math.Sqrt 16 }} <!-- 平方根 -->
<!-- 集合 -->
{{ slice "a" "b" "c" }} <!-- 创建切片 -->
{{ first 3 .Pages }} <!-- 前N个 -->
{{ last 3 .Pages }} <!-- 后N个 -->
{{ after 3 .Pages }} <!-- 第N个之后 -->
{{ range where .Pages "Section" "posts" }} <!-- 过滤 -->
{{ range sort .Pages "Title" "asc" }} <!-- 排序 -->
{{ .Pages.Reverse }} <!-- 反转 -->
{{ in .Params.tags "Hugo" }} <!-- 包含判断 -->
{{ intersect $a $b }} <!-- 交集 -->
{{ union $a $b }} <!-- 并集 -->
<!-- 类型转换 -->
{{ cast.ToString 123 }} <!-- 转字符串 -->
{{ cast.ToInt "42" }} <!-- 转整数 -->
{{ dict "key" "value" }} <!-- 创建Map -->
<!-- URL -->
{{ .RelPermalink }} <!-- 相对 URL -->
{{ .Permalink }} <!-- 绝对 URL -->
{{ urls.AbsLangURL "/about/" }} <!-- 带语言前缀 -->
{{ .Title | urls.URLize }} <!-- URL友好格式 -->
<!-- 编码 -->
{{ $json := dict "name" "Hugo" | jsonify }}
{{ $encoded := "hello" | encoding.Base64Encode }}
<!-- 加密 -->
{{ crypto.MD5 "hello" }}
{{ crypto.SHA256 "hello" }}
<!-- 路径 -->
{{ path.Base "/a/b/c.txt" }} <!-- c.txt -->
{{ path.Dir "/a/b/c.txt" }} <!-- /a/b -->
{{ path.Ext "/a/b/c.txt" }} <!-- .txt -->
{{ path.Join "a" "b" "c" }} <!-- a/b/c -->
<!-- 转换 -->
{{ .Content | transform.Plainify }} <!-- 去HTML -->
{{ .Summary | transform.Markdownify }} <!-- Markdown转HTML -->
{{ transform.Highlight .Code "go" }} <!-- 代码高亮 -->
<!-- 语言 -->
{{ i18n "readMore" }} <!-- 翻译 -->
{{ lang.FormatNumber 1234567 }} <!-- 数字格式化 -->
<!-- 安全 -->
{{ $html | safeHTML }} <!-- 标记安全HTML -->
{{ $css | safeCSS }} <!-- 标记安全CSS -->
<!-- 哈希 -->
{{ hash.FNV32a "text" }} <!-- FNV32a哈希 -->
{{ hash.XxHash "text" }} <!-- xxHash哈希 -->
<!-- 单词变形 -->
{{ "cats" | singularize }} <!-- 单数化: cat -->
{{ "cat" | pluralize }} <!-- 复数化: cats -->
<!-- 类型判断 -->
{{ reflect.IsMap .Params }} <!-- 是否为Map -->
{{ reflect.IsSlice .Tags }} <!-- 是否为切片 -->
<!-- 格式化输出 -->
{{ printf "%s: %d" "Count" 10 }} <!-- 格式化字符串 -->
{{ errorf "Error: %s" . }} <!-- 错误(中断构建) -->
{{ warnf "Warning: %s" . }} <!-- 警告 -->
<!-- 模板系统 -->
{{ templates.Exists "partial.html" }} <!-- 模板是否存在 -->
<!-- Hugo信息 -->
{{ hugo.Version }} <!-- 版本号 -->
{{ hugo.IsProduction }} <!-- 是否生产环境 -->
{{ hugo.IsServer }} <!-- 是否开发服务器 -->
<!-- 操作系统 -->
{{ os.Getenv "HUGO_ENV" }} <!-- 环境变量 -->
{{ os.FileExists "/path/file" }} <!-- 文件是否存在 -->
Partials
{{ partial "header.html" . }}
{{ partial "nav.html" .Site }}
定义和继承
<!-- baseof.html -->
{{ block "main" . }}{{ end }}
<!-- single.html -->
{{ define "main" }}
<article>{{ .Content }}</article>
{{ end }}
配置
基本配置
baseURL = 'https://example.org/'
languageCode = 'zh-cn'
title = '我的博客'
theme = 'ananke'
buildDrafts = false
buildFuture = false
buildExpired = false
enableEmoji = true
enableRobotsTXT = true
summaryLength = 70
# 时区
timeZone = 'Asia/Shanghai'
# CJK语言检测
hasCJKLanguage = true
# 构建超时
timeout = '60s'
# 标题大小写风格
titleCaseStyle = 'ap' # ap, chicago, go, firstupper, none
[pagination]
pagerSize = 10
URL 配置
[permalinks]
posts = '/:year/:month/:title/'
# 占位符: :year :month :day :title :slug :section :filename
调试配置
# 模板性能分析
templateMetrics = false
templateMetricsHints = false
# 各种警告
printI18nWarnings = false
printPathWarnings = false
printUnusedTemplates = false
# 忽略特定日志
ignoreLogs = ['warning-id']
多语言配置
defaultContentLanguage = 'zh'
[languages]
[languages.zh]
title = '我的博客'
weight = 1
contentDir = 'content/zh'
[languages.en]
title = 'My Blog'
weight = 2
contentDir = 'content/en'
多语言内容管理
文件名后缀方式:
content/posts/
├── article.en.md
├── article.zh.md
└── article.ja.md
独立内容目录方式:
content/
├── zh/posts/article.md
└── en/posts/article.md
translationKey 手动关联
当翻译页面路径不同时:
<!-- content/about-us.en.md -->
---
title: "About Us"
translationKey: "about"
---
<!-- content/关于我们.zh.md -->
---
title: "关于我们"
translationKey: "about"
---
模板中获取翻译:
{{ if .IsTranslated }}
{{ range .Translations }}
<a href="{{ .RelPermalink }}">{{ .Language.LanguageName }}</a>
{{ end }}
{{ end }}
<!-- 获取所有翻译(包括当前语言) -->
{{ range .AllTranslations }}
<a href="{{ .RelPermalink }}">{{ .Language.LanguageName }}</a>
{{ end }}
菜单配置
[menu]
[[menu.main]]
name = '首页'
url = '/'
weight = 1
[[menu.main]]
name = '博客'
url = '/posts/'
weight = 2
标记配置
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
[markup.highlight]
codeFences = true
lineNos = true
style = 'monokai'
[markup.tableOfContents]
startLevel = 2
endLevel = 4
分类法配置
[taxonomies]
tag = 'tags'
category = 'categories'
author = 'authors'
短代码
内置短代码
<!-- 图片 -->
{{< figure src="/img/photo.jpg" title="标题" alt="描述" >}}
<!-- YouTube 视频 -->
{{< youtube VIDEO_ID >}}
<!-- Vimeo 视频 -->
{{< vimeo VIDEO_ID >}}
<!-- GitHub Gist -->
{{< gist username gist_id >}}
{{< gist username gist_id filename.py >}}
<!-- Instagram -->
{{< instagram POST_ID >}}
<!-- X/Twitter -->
{{< x id="TWEET_ID" >}}
<!-- 代码高亮 -->
{{< highlight python "linenos=table,hl_lines=2 3" >}}
def hello():
print("Hello")
{{< /highlight >}}
<!-- QR 码 -->
{{< qr text="https://example.com" level="high" />}}
<!-- 参数引用 -->
{{< param "author" >}}
{{< param "social.github" >}}
<!-- 折叠内容 -->
{{< details summary="点击展开" open=true >}}
隐藏的内容
{{< /details >}}
<!-- 页面引用 -->
{{< ref "about.md" >}}
{{< relref "posts/my-post.md" >}}
自定义短代码
<!-- layouts/shortcodes/alert.html -->
{{ $type := .Get "type" | default "info" }}
<div class="alert alert-{{ $type }}">
{{ .Inner | markdownify }}
</div>
使用:
{{< alert type="warning" >}}
警告信息
{{< /alert >}}
内联短代码
在配置中启用:
[security]
enableInlineShortcodes = true
在内容中定义:
{{< year.inline >}}
{{- now.Year -}}
{{< /year.inline >}}
版权所有 © {{< year.inline />}}
嵌套短代码
{{< gallery >}}
{{< image src="/img/1.jpg" alt="图片1" >}}
{{< image src="/img/2.jpg" alt="图片2" >}}
{{< /gallery >}}
语法区别
| 语法 | Markdown 渲染 | 目录包含 |
|---|---|---|
{{< >}} | 否 | 否 |
{{% %}} | 是 | 是 |
页面变量
页面属性
| 变量 | 说明 |
|---|---|
.Title | 页面标题 |
.Content | 页面内容 |
.Summary | 摘要 |
.Date | 发布日期 |
.Lastmod | 最后修改日期 |
.Draft | 是否草稿 |
.WordCount | 字数 |
.ReadingTime | 阅读时间 |
.RelPermalink | 相对 URL |
.Permalink | 绝对 URL |
.Section | 所属分区 |
.Type | 内容类型 |
.Kind | 页面类型 |
.Weight | 权重 |
.Params | 自定义参数 |
站点属性
| 变量 | 说明 |
|---|---|
.Site.Title | 站点标题 |
.Site.BaseURL | 基础 URL |
.Site.LanguageCode | 语言代码 |
.Site.Params | 站点参数 |
.Site.Menus | 菜单 |
.Site.RegularPages | 所有常规页面 |
.Site.Pages | 所有页面 |
.Site.Taxonomies | 分类法 |
排序方法
{{ range .Pages.ByTitle }}
{{ range .Pages.ByDate }}
{{ range .Pages.ByDate.Reverse }}
{{ range .Pages.ByPublishDate }}
{{ range .Pages.ByLastmod }}
{{ range .Pages.ByWeight }}
{{ range .Pages.ByLength }}
分页
{{ $paginator := .Paginate .Pages }}
{{ range $paginator.Pages }}
<h2>{{ .Title }}</h2>
{{ end }}
{{ if $paginator.HasPrev }}
<a href="{{ $paginator.Prev.URL }}">上一页</a>
{{ end }}
<span>{{ $paginator.PageNumber }} / {{ $paginator.TotalPages }}</span>
{{ if $paginator.HasNext }}
<a href="{{ $paginator.Next.URL }}">下一页</a>
{{ end }}
构建选项
通过 Front Matter 控制页面构建行为:
---
build:
render: always # always, never
list: always # always, local, never
publishResources: true
---
无头页面示例
---
title: "共享组件"
build:
render: never
list: local
---
Go 模板语句
<!-- 条件判断 -->
{{ if .Title }}{{ end }}
{{ if eq .Type "posts" }}{{ end }}
{{ if and .Title .Content }}{{ end }}
{{ if or .Params.featured .Params.pinned }}{{ end }}
{{ if not .Draft }}{{ end }}
{{ if eq .Section "posts" }}
<!-- posts section -->
{{ else if eq .Section "tutorials" }}
<!-- tutorials section -->
{{ else }}
<!-- other -->
{{ end }}
<!-- with 语句 -->
{{ with .Params.author }}
<p>作者:{{ . }}</p>
{{ end }}
<!-- 循环 -->
{{ range .Site.RegularPages }}
<h2>{{ .Title }}</h2>
{{ end }}
{{ range $index, $page := .Site.RegularPages }}
<div class="post-{{ $index }}">{{ $page.Title }}</div>
{{ end }}
<!-- 循环控制(Hugo 0.124+) -->
{{ range .Pages }}
{{ if .Draft }}
{{ continue }} <!-- 跳过本次迭代 -->
{{ end }}
{{ if gt .WordCount 5000 }}
{{ break }} <!-- 跳出循环 -->
{{ end }}
{{ end }}
<!-- 定义块 -->
{{ define "main" }}
<article>{{ .Content }}</article>
{{ end }}
<!-- 定义和继承 -->
{{ block "main" . }}{{ end }}
<!-- 变量赋值 -->
{{ $title := .Title }}
{{ $pages := .Site.RegularPages }}
Partial Decorators(部分装饰器)
<!-- 调用装饰器 -->
{{ with partial "components/wrapper.html" . }}
<p>被包装的内容</p>
{{ .Content }}
{{ end }}
<!-- 装饰器模板 (layouts/partials/components/wrapper.html) -->
<div class="wrapper">
{{ templates.Inner . }}
</div>
<!-- 传递上下文 -->
{{ $ctx := dict "page" . "title" "标题" }}
{{ with partial "components/card.html" $ctx }}
<p>{{ .page.Summary }}</p>
{{ end }}
<!-- 嵌套装饰器 -->
{{ with partial "components/section.html" $ctx }}
{{ with partial "components/column.html" . }}
{{ with partial "components/card.html" . }}
<p>内容</p>
{{ end }}
{{ end }}
{{ end }}
资源处理
<!-- 获取资源 -->
{{ $css := resources.Get "css/main.css" }}
{{ $image := resources.Get "images/photo.jpg" }}
{{ $remote := resources.GetRemote "https://example.com/data.json" }}
<!-- 处理资源 -->
{{ $css | minify }}
{{ $css | fingerprint }}
{{ $css | resources.Concat "css/bundle.css" }}
<!-- CSS 打包(Hugo 0.150+) -->
{{ $css := resources.Get "css/main.css" | css.Build }}
{{ $opts := dict "minify" true "sourceMap" "linked" }}
{{ $css := resources.Get "css/main.css" | css.Build $opts }}
<!-- 图片处理 -->
{{ $image := resources.Get "images/photo.jpg" }}
{{ $resized := $image.Resize "800x" }}
{{ $webp := $image.Resize "800x webp" }}
{{ $fitted := $image.Fit "800x600" }}
{{ $filled := $image.Fill "400x300 Center" }}
{{ $cropped := $image.Crop "200x200 Smart" }}
<!-- 图片滤镜 -->
{{ $image | images.Filter (images.Grayscale) (images.GaussianBlur 6) }}
<!-- Padding 滤镜(Hugo 0.120+) -->
{{ $padded := $image | images.Filter (images.Padding 10 10 10 10 "#ffffff") }}
<!-- 提取图片颜色 -->
{{ $colors := $image.Colors }}
<!-- EXIF 信息 -->
{{ with $image.Exif }}
Date: {{ .Date }}
Lat/Long: {{ .Lat }}/{{ .Long }}
{{ end }}
<!-- 响应式图片 -->
{{ $small := $image.Resize "400x webp" }}
{{ $medium := $image.Resize "800x webp" }}
{{ $large := $image.Resize "1200x webp" }}
<img
src="{{ $large.RelPermalink }}"
srcset="{{ $small.RelPermalink }} 400w,
{{ $medium.RelPermalink }} 800w,
{{ $large.RelPermalink }} 1200w"
sizes="(max-width: 800px) 100vw, 800px"
loading="lazy">
图片处理配置
[imaging]
quality = 75
compression = "lossy" # lossy(有损), lossless(无损,仅 WebP)
resampleFilter = "lanczos" # box, lanczos, catmullrom, mitchellnetravali, linear, nearestneighbor
anchor = "smart" # Smart, TopLeft, Top, TopRight, Left, Center, Right, BottomLeft, Bottom, BottomRight
bgColor = "#ffffff"
[imaging.webp]
hint = "photo" # drawing, icon, photo, picture, text
method = 2 # 压缩努力程度(0-6)
useSharpYuv = false # 锐利的 YUV 转换
[imaging.meta]
sources = ["exif", "iptc"] # 元数据来源: exif, iptc, xmp
fields = ["**"] # 包含的字段(glob 模式)
[imaging.exif]
disableDate = false
disableLatLong = false
includeFields = ""
excludeFields = ""
图片类型判断函数
| 函数 | 说明 |
|---|---|
reflect.IsImageResource | 是否为图片资源 |
reflect.IsImageResourceProcessable | 是否可被处理(调整大小、裁剪等) |
reflect.IsImageResourceWithMeta | 是否可提取元数据 |
重采样滤镜选择
| 滤镜 | 适用场景 |
|---|---|
lanczos | 照片,质量优先(推荐) |
catmullrom | 照片,平衡质量和速度 |
nearestneighbor | 像素艺术、图标 |
box | 缩小图片,速度优先 |
图片处理方法对比
| 方法 | 说明 | 是否保持比例 |
|---|---|---|
Resize | 指定尺寸缩放 | 可选 |
Fit | 适应尺寸,不超出 | 是 |
Fill | 裁剪到精确尺寸 | 否 |
Crop | 裁剪不缩放 | 是 |
Process | 统一处理接口 | 取决于参数 |
WebP Hint 选项
| 值 | 适用场景 |
|---|---|
drawing | 手绘或线条图 |
icon | 图标、缩略图 |
photo | 户外照片(默认) |
picture | 室内照片、人像 |
text | 截图、文档扫描 |
部署配置
GitHub Actions
- name: Build with Hugo
run: hugo --gc --minify
Netlify
[build]
publish = "public"
command = "hugo --gc --minify"
[context.production.environment]
HUGO_VERSION = "0.121.1"
Vercel
Framework preset: Hugo
内容适配器
内容适配器用于从外部数据动态创建页面。
基本结构
content/
└── books/
├── _content.gotmpl # 内容适配器
└── _index.md
AddPage 方法
{{/* 创建页面内容 */}}
{{ $content := dict
"mediaType" "text/markdown"
"value" "页面内容"
}}
{{/* 创建页面 */}}
{{ $page := dict
"content" $content
"path" "article-slug"
"title" "文章标题"
"dates" (dict "date" (time.AsTime "2024-01-15"))
"params" (dict "author" "张三" "tags" (slice "Hugo"))
}}
{{ .AddPage $page }}
AddResource 方法
{{ with resources.Get "images/cover.jpg" }}
{{ $content := dict
"mediaType" .MediaType.Type
"value" .
}}
{{ $resource := dict
"content" $content
"path" "article/cover.jpg"
}}
{{ $.AddResource $resource }}
{{ end }}
获取远程数据
{{ $url := "https://api.example.com/data.json" }}
{{ with try (resources.GetRemote $url) }}
{{ with .Err }}
{{ errorf "获取失败: %s" . }}
{{ else with .Value }}
{{ $data := . | transform.Unmarshal }}
{{ range $data }}
{{/* 创建页面 */}}
{{ end }}
{{ end }}
{{ end }}
多语言支持
{{/* 对所有语言生效 */}}
{{ .EnableAllLanguages }}
页面字段说明
| 字段 | 说明 | 必填 |
|---|---|---|
path | 页面逻辑路径 | 是 |
title | 页面标题 | 否(推荐) |
content.mediaType | 内容类型,默认 text/markdown | 否 |
content.value | 内容字符串 | 否 |
dates.date | 创建日期 | 否 |
dates.lastmod | 最后修改日期 | 否 |
params | 自定义参数 | 否 |
图表支持
GoAT 图表
```goat
+-------+ +-------+
| A | --> | B |
+-------+ +-------+
### Mermaid 图表
渲染钩子 (`layouts/_default/_markup/render-codeblock-mermaid.html`):
```html
<pre class="mermaid">
{{ .Inner | htmlEscape | safeHTML }}
</pre>
{{ .Page.Store.Set "hasMermaid" true }}
基础模板中加载:
{{ 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 }}
Mermaid 示例
```mermaid
flowchart TD
A[开始] --> B{判断}
B -->|是| C[处理]
B -->|否| D[结束]
## Markdown 属性
### 基本语法
```markdown
段落文字。{#my-id .my-class}
# 标题 {.text-center}
{width="800" height="600"}
[链接](url){target="_blank"}
启用配置
[markup]
[markup.goldmark]
[markup.goldmark.parser]
attribute = true
数学公式
行内公式
质能方程 \(E = mc^2\) 揭示了质量和能量的关系。
块级公式
$$
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
$$
服务端渲染(Hugo 0.122+)
配置 passthrough 扩展:
[markup]
[markup.goldmark]
[markup.goldmark.extensions]
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
inline = [['\(', '\)']]
使用 transform.ToMath:
<!-- 基本用法 -->
{{ transform.ToMath "E = mc^2" }}
<!-- 指定输出格式 -->
{{ $opts := dict "output" "htmlAndMathml" }}
{{ transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" $opts }}
<!-- 块级公式 -->
{{ $opts := dict "displayMode" true "output" "htmlAndMathml" }}
{{ transform.ToMath .Inner $opts }}
transform.ToMath 选项:
| 选项 | 说明 | 默认值 |
|---|---|---|
displayMode | 是否为块级公式 | false |
output | 输出格式:mathml、html、htmlAndMathml | mathml |
errorColor | 错误颜色 | #cc0000 |
throwOnError | 出错时是否抛出异常 | true |
macros | 自定义宏 |
客户端渲染 MathJax
{{ if .Store.Get "hasMath" }}
<script>
MathJax = {
tex: {
inlineMath: [['\\(', '\\)']],
displayMath: [['\\[', '\\]'], ['$$', '$$']]
}
};
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" async></script>
{{ end }}
常见问题
中文 URL 问题
# hugo.toml
disablePathToLower = true
代码高亮不显示
[markup]
[markup.highlight]
noClasses = false
草稿不显示
hugo server -D
# 或
hugo --buildDrafts
热重载不工作
hugo server --disableFastRender
内存不足
hugo --gc