本文档介绍 jijian 主题的模板结构、继承关系和自定义方法,帮助你深入理解主题的工作原理并进行定制开发。


模板结构概览

jijian 主题采用 Hugo 标准的模板层次结构:

theme_pps4rsdaah0o/egro4bjfetr.oiabbsltasr/pihhfcpctppbsscetaacseettbfcvirhtjualiieresaaeeoaooooorohodrunuvxxeciioenatsilsansrcasslaaorrvcssecamiatcsgttmolglrTwm.atengtmhr.ssddtdte.ttairmtnhht.eepdiultehltnokl.sicxw.ee.arh__daee_sooohnnloxsebraixtxf.eh.vhmhrrhl.tmncl_nplrrmtddap_csiepctmtl.h.the.lrt..t.hmear_itoa.e_m__tech/l.saIlahthmtshdmhhmhtltvuicssthdwlhfenaeihelm.ytmtlm.t.lttltma_mco.tit_oeosgrm.t..ghomlmlhmhmmml.lbonh.omhrao/rdahmhh.tulltltlllhisnsthnleddtas_tltthmtmmtn.s.mt_ac.ep.jmmmtlsllmkh.hlmldohrhhslllm/lsthtliiut..tol.mtmsnnmhhmnhlmltgtlttl.tl.s.mmhmh.hlltlthtm#########################m#tm######l##########lmlRHlSSOT#4ST##VEpw0/线SM#GOeiS4LntcHthTGeeMrrmLa/apX.hoCragrds

模板继承关系

基础模板层次

baseohhmffeeao.aaiohddntt.MCFteLslasteemheSaerobiireerxlttSvm.glnscar.tmaiphoogthrmhe(lcloxstclbtptesc.pcicstnoap_cmkeroordhohoavh.md(ntechl.ecsaiamtrre.hl_enae(ha.tntrmmtdshtfsgrm(tdh_s_eela..tm(o))/rdamctmlp_nlhhmloas_lrmeaoit(.ttltp.j)ulttscshmm()ehhs)(maito.tll(r.tob.o.nhm.hmnshnhst)l((/htl..t_t.mtmh)hmlmhl()mlttliltlmmsm))lltl).h)tml

核心模板详解

baseof.html - 基础模板

所有页面的基础骨架,定义了整体 HTML 结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode }}" dir="auto">
<head>
    {{- partial "head.html" . -}}
</head>
<body class="{{ if .IsHome }}home{{ end }}">
    {{- partial "header.html" . -}}
    <main class="main">
        {{- block "main" . }}{{- end }}
    </main>
    {{- partial "footer.html" . -}}
</body>
</html>

关键点

  • 使用 block "main" 定义主内容区块
  • 子模板通过 define "main" 填充内容

single.html - 文章页模板

单篇文章的展示模板:

(t(o((c((ces(obp.dhpmro(hiaomestttrseatrm_etnd_alp__tcmn)oinsressca.utltovhmaa.n_tb.thslmshit.il.tomhn)hmnltktl_)msm)ll.li)h)sttm.lh)tml)

list.html - 列表页模板

文章列表的展示模板,支持三种首页模式:

cpaorrdtMaoldMeodecarpdo.rhttamll.html

head.html - 头部模板

包含所有 <head> 内的内容:

head.MFCSeheaSExttvSOtmaielcvdkcoxsnhieeop_cdaesynech_rwcwnaehsprogrmeeoirrdaatrpdas_dttsp.j.ihhsho.totnhmnmtl.lmhlt(ml)

自定义模板

方法一:覆盖主题模板

在站点根目录的 layouts 文件夹中创建同名模板文件,会自动覆盖主题模板:

your-ltsahiyetomeu_pej/tdasiser/j/ftiasifaluiaonalnlo/ytgsto/l/eu_pertda..serhh/ftttasifmmuiaolllnlotgst/l/eer..##hhttmmllsfionogtleer..hhttmmll

方法二:使用扩展模板

主题提供了 extend_head.htmlextend_footer.html 扩展点:

添加自定义 CSS/JS

创建 layouts/partials/extend_head.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!-- 自定义样式 -->
<style>
.my-custom-class {
    color: red;
}
</style>

<!-- 引入外部 CSS -->
<link rel="stylesheet" href="https://example.com/style.css">

<!-- 自定义脚本 -->
<script>
console.log('Custom script loaded');
</script>

创建 layouts/partials/extend_footer.html

1
2
3
4
5
6
7
<!-- 页脚自定义内容 -->
<div class="custom-footer">
    自定义页脚内容
</div>

<!-- 引入外部 JS -->
<script src="https://example.com/script.js"></script>

方法三:创建新的部分模板

创建自定义部分模板并在主模板中引用:

  1. 创建 layouts/partials/my-component.html
1
2
3
<div class="my-component">
    {{ .Text }}
</div>
  1. 在其他模板中引用:
1
{{ partial "my-component.html" (dict "Text" "Hello World") }}

页面类型模板

归档页 (archives.html)

时间线归档页面,按年份和月份展示所有文章:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{{ define "main" }}
<div class="archive">
    <h1>{{ .Title }}</h1>
    {{ range .Site.RegularPages.GroupByDate "2006" }}
    <div class="archive-year">
        <h2>{{ .Key }}</h2>
        {{ range .Pages.GroupByDate "01月" }}
        <div class="archive-month">
            <h3>{{ .Key }}</h3>
            {{ range .Pages }}
            <article>
                <time>{{ .Date.Format "01-02" }}</time>
                <a href="{{ .Permalink }}">{{ .Title }}</a>
            </article>
            {{ end }}
        </div>
        {{ end }}
    </div>
    {{ end }}
</div>
{{ end }}

访问路径/archives/

配置方法

1
2
3
4
5
6
menu:
  main:
    - identifier: archives
      name: 归档
      url: /archives/
      weight: 20

搜索页 (search.html)

Pagefind 搜索页面:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{{ define "main" }}
<div class="search">
    <h1>{{ .Title }}</h1>
    <div id="search"></div>
    <link href="/pagefind/pagefind-ui.css" rel="stylesheet">
    <script src="/pagefind/pagefind-ui.js"></script>
    <script>
    new PagefindUI({
        element: "#search",
        showSubResults: true,
        showImages: false
    });
    </script>
</div>
{{ end }}

访问路径/search/

构建搜索索引

1
hugo && npx pagefind --site public --output-path public/pagefind

标签/分类页 (terms.html)

标签和分类的列表页:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{{ define "main" }}
<div class="terms">
    <h1>{{ .Title }}</h1>
    <ul>
    {{ range .Pages }}
        <li>
            <a href="{{ .Permalink }}">{{ .Title }}</a>
            <span>{{ len .Pages }} 篇</span>
        </li>
    {{ end }}
    </ul>
</div>
{{ end }}

访问路径

  • 标签:/tags/
  • 分类:/categories/

404 页面

错误页面模板:

1
2
3
4
5
6
7
{{ define "main" }}
<div class="error-404">
    <h1>404</h1>
    <p>页面未找到</p>
    <a href="{{ .Site.BaseURL }}">返回首页</a>
</div>
{{ end }}

模板变量

全局变量

在模板中可使用的 Hugo 变量:

变量说明
.Site站点对象
.Page当前页面对象
.Title页面标题
.Content页面内容
.Summary页面摘要
.Date发布日期
.Lastmod最后修改日期
.Permalink页面永久链接
.RelPermalink页面相对链接
.Params页面参数
.Site.Params站点参数

常用方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 获取配置参数 -->
{{ .Site.Params.author }}

<!-- 条件判断 -->
{{ if .Site.Params.ShowToc }}
    {{ partial "toc.html" . }}
{{ end }}

<!-- 循环 -->
{{ range .Site.Menus.main }}
    <a href="{{ .URL }}">{{ .Name }}</a>
{{ end }}

<!-- 日期格式化 -->
{{ .Date.Format "2006年01月02日" }}

<!-- 字数统计 -->
{{ .WordCount }}

<!-- 阅读时长 -->
{{ .ReadingTime }}

部分模板详解

toc.html - 目录模板

生成文章目录,支持多种显示模式:

配置参数

1
2
3
4
5
6
7
params:
  ShowToc: true
  TocOpen: true
  TocPosition: auto      # left / right / auto
  tocHover: true         # 悬浮模式
  tocHoverDelay: 200     # 悬浮延迟
  tocHideDelay: 2000     # 隐藏延迟

social_icons.html - 社交图标模板

显示社交图标,支持悬浮二维码:

配置示例

1
2
3
4
5
6
params:
  socialIcons:
    - name: bilibili
      url: https://space.bilibili.com/xxxxxx
      title: 哔哩哔哩
      hoverImage: /img/bilibili-qr.png

comments.html - 评论模板

集成 Giscus 评论系统:

配置示例

1
2
3
4
5
6
7
params:
  comments: true
  giscus:
    repo: "user/repo"
    repoId: "R_xxxxx"
    category: "Announcements"
    categoryId: "DIC_xxxxx"

自定义示例

添加文章底部广告

创建 layouts/partials/extend_footer.html

1
2
3
4
5
{{ if .IsPage }}
<div class="post-ad">
    <p>如果觉得文章有帮助,请支持作者 ❤️</p>
</div>
{{ end }}

添加阅读进度条

创建 layouts/partials/extend_head.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<style>
.reading-progress {
    position: fixed;
    top: 0;
    left: 0;
    width: 0%;
    height: 3px;
    background: linear-gradient(to right, #4CAF50, #2196F3);
    z-index: 9999;
    transition: width 0.1s ease;
}
</style>

创建 layouts/partials/extend_footer.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{{ if .IsPage }}
<div class="reading-progress" id="readingProgress"></div>
<script>
window.addEventListener('scroll', function() {
    var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
    var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
    var scrolled = (winScroll / height) * 100;
    document.getElementById("readingProgress").style.width = scrolled + "%";
});
</script>
{{ end }}

自定义文章归档样式

创建 layouts/_default/archives.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{{ define "main" }}
<div class="archive-custom">
    <h1>文章归档</h1>
    {{ range .Site.RegularPages.GroupByDate "2006" }}
    <div class="year-group">
        <h2 class="year-title">{{ .Key }}年</h2>
        {{ range .Pages }}
        <article class="archive-item">
            <time datetime="{{ .Date.Format "2006-01-02" }}">
                {{ .Date.Format "01-02" }}
            </time>
            <a href="{{ .Permalink }}">{{ .Title }}</a>
            <span class="category">
                {{ range .Params.categories }}{{ . }}{{ end }}
            </span>
        </article>
        {{ end }}
    </div>
    {{ end }}
</div>
{{ end }}