跳到主要内容

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}

![图片](photo.jpg){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、htmlAndMathmlmathml
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

有用的链接