0x00 基础知识

弄了一天的主题,本身好久都没碰前端的东西,有点生疏,弄完之后感觉还不错,本文主要参考官方的函数文档:https://gohugo.io/functions/

文件结构:

├── 404.html
├── _default
│   ├── archives.html
│   ├── baseof.html #这个就是Hugo定义的mian文件
│   ├── index.json
│   ├── list.html
│   ├── search.html
│   └── single.html
├── index.html
└── partials
    ├── head.html
    ├── head_fonts.html
    ├── hook_head_end.html
    ├── pagination.html
    └── sidebar.html

文件分析

这个mian就是baseof.html,里面包含了head.htmlsidebar.html两个文件:

{{ partial "head.html" . }}
  <body class="{{ .Site.Params.themeColor }} {{if .Site.Params.layoutReverse}}layout-reverse{{end}}">
  {{ partial "sidebar.html" . }}
    <main class="content container">
    {{ block "main" . -}}{{- end }}
    </main>

    {{ if not .Site.IsServer }}
      {{ template "_internal/google_analytics.html" . }}
    {{ end }}
  </body>
</html>

head.html文件里面一般是加入各种基础的css文件和js文件:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"{{with .Site.LanguageCode}} xml:lang="{{.}}" lang="{{.}}"{{end}}>
<head>
  <link href="https://gmpg.org/xfn/11" rel="profile">
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  {{ hugo.Generator }}

  <!-- Enable responsiveness on mobile devices-->
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  {{ if .IsHome -}}
  <title>{{ .Site.Title }}</title>
  {{- else -}}
  <title>{{ .Title }} &middot; {{ .Site.Title }}</title>
  {{- end }}
  <meta name="description" content="{{if .IsHome}}{{ $.Site.Params.description }}{{else}}{{.Description}}{{end}}" />

  <!-- CSS -->
  <link type="text/css" rel="stylesheet" href="/css/print.css" media="print">
  <link type="text/css" rel="stylesheet" href="/css/poole.css">
  <link type="text/css" rel="stylesheet" href="/css/syntax.css">
  <link type="text/css" rel="stylesheet" href="/css/hyde.css">
  {{ partial "head_fonts.html" . }}

  <!-- Icons -->
  <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
  <link rel="shortcut icon" href="/favicon.png">

  <!-- RSS etc -->
  {{ range .AlternativeOutputFormats -}}
    {{ printf `<link href="%s" rel="%s" type="%s" title="%s" />` .Permalink .Rel .MediaType.Type $.Site.Title | safeHTML }}
  {{ end -}}

  {{ partial "hook_head_end.html" . }}
</head>

主要文件的渲染是在index.html开始,开头的时候包含了main,也就是包含了baseof.html:

{{ define "main" -}}
<div class="posts">
  {{ $paginator := .Paginate (where .Site.RegularPages "Type" .Site.Params.PostDir) }}
  {{ range $paginator.Pages }}
  <article class="post">
    <h1 class="post-title">
      <a href="{{ .Permalink }}">{{ .Title }}</a>
    </h1>
    <time datetime="{{ .Date.Format "2006-01-02T15:04:05Z0700" }}" class="post-date">{{ .Date.Format "Mon, Jan 2, 2006" }}</time>

  </article>
  {{ end }}
</div>
{{- partial "pagination.html" . -}}

{{- end }}

0x01 添加搜索页面

首先这个主题是没有搜索功能的,为了平时搜索文章的时候方便,就添加了一个搜索的功能,

_default目录下添加search.html 文件:

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/3.2.0/fuse.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/jquery.mark.min.js"></script>
<script src="/js/search.js"></script>

{{ partial "head.html" . }}
<style>
    input
    {

        -webkit-appearance: none;
        display: block;
        width: 80%;
        padding: 8px;
        margin-bottom: 10px;
        font-size: 1rem;
        line-height: 1.5;
        border: 1px solid #ced4da;
        border-radius: .25rem;



    }

</style>
<body class="{{ .Site.Params.themeColor }} {{if .Site.Params.layoutReverse}}layout-reverse{{end}}">
{{ partial "sidebar.html" . }}
<main class="content container">
    {{ block "main" . -}}
    <section class="resume-section p-3 p-lg-5 d-flex flex-column">
        <div class="my-auto" >
            <form action="{{ "search" | absURL }}">
            <input id="search-query" name="s" placeholder="输入关键词..."/>
            </form>
            <div id="search-results">


            </div>
        </div>
    </section>
    <!-- this template is sucked in by search.js and appended to the search-results div above. So editing here will adjust style -->
    <script id="search-result-template" type="text/x-js-template">
        <div id="summary-${key}">
            <h2><a href="${link}">${title}</a></h2>


        </div>
    </script>
    {{- end }}
</main>

{{ if not .Site.IsServer }}
{{ template "_internal/google_analytics.html" . }}
{{ end }}
</body>
</html>

_default目录下添加index.json 文件:

{{- $.Scratch.Add "index" slice -}}
{{- range .Site.RegularPages -}}
{{- $.Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "categories" .Params.categories "contents" .Plain "permalink" .Permalink) -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

config.toml文件下添加以下内容:

[outputs]
  home = ["HTML", "RSS", "JSON"]
[outputFormats]
[outputFormats.HTML]
mediaType = "text/html"
[Menus]
  main = [
      {Name = "Search",weight = 1, URL = "search"},
]

在博客主目录的content目录下新建文件search.md:

---
title: "Search Result"
date: 2019-05-28
layout: "search"
---

0x02 添加分页页面

太多文章了,需要一个分页功能会比较方便。添加以下代码:

{{ $paginator := .Paginate (where .Site.RegularPages "Type" .Site.Params.PostDir) }}
  {{ range $paginator.Pages }}
  ......
{{ end }}

index.html做修改,在后面包含pagination.html文件:

{{- partial "pagination.html" . -}}

修改完后的index.html文件:

{{ define "main" -}}
<div class="posts">
  {{ $paginator := .Paginate (where .Site.RegularPages "Type" .Site.Params.PostDir) }}
  {{ range $paginator.Pages }}
  <article class="post">
    <h1 class="post-title">
      <a href="{{ .Permalink }}">{{ .Title }}</a>
    </h1>
    <time datetime="{{ .Date.Format "2006-01-02T15:04:05Z0700" }}" class="post-date">{{ .Date.Format "Mon, Jan 2, 2006" }}</time>

  </article>
  {{ end }}
</div>
{{- partial "pagination.html" . -}}

{{- end }}

partials目录下添加pagination.html文件,内容如下:

{{ if gt .Paginator.TotalPages 1 }}
<nav class='pagination'>
  {{ $.Scratch.Set "hasPrevDots" false }}
  {{ $.Scratch.Set "hasNextDots" false }}

  {{ range .Paginator.Pagers }}
  {{ if eq . $.Paginator }}
  <span class='pagination-item current'>
                    {{- .PageNumber -}}
                </span>
  {{ else if or (or (eq . $.Paginator.First) (eq . $.Paginator.Prev)) (or  (eq . $.Paginator.Next) (eq . $.Paginator.Last )) }}
  <a class='pagination-item' href='{{ .URL }}'>
    {{- .PageNumber -}}
  </a>
  {{ else }}
  {{ if and (not ($.Scratch.Get "hasPrevDots")) (lt .PageNumber $.Paginator.PageNumber)  }}
  {{ $.Scratch.Set "hasPrevDots" true }}
  <span class='pagination-item dots'>&hellip;</span>
  {{ else if and (not ($.Scratch.Get "hasNextDots")) (gt .PageNumber $.Paginator.PageNumber) }}
  {{ $.Scratch.Set "hasNextDots" true }}
  <span class='pagination-item dots'>&hellip;</span>
  {{ end }}
  {{ end }}
  {{ end }}
</nav>
{{ end }}

分页的数量可以在congfig.tml文件上添加参数:

Paginate = 4  #4代表每页4篇文章

0x03 添加目录(TOC)

这个功能我是在大佬博客https://ichochy.com/上面看到不错的滑动效果,然后借鉴进行修改:

在js目录下添加toc.js文件,加入以下内容:

//文档加载后执行 fn
function ready(fn) {
    if (window.addEventListener) { 
        window.addEventListener('DOMContentLoaded', function () {
            //注销时间,避免重复触发
            document.removeEventListener('DOMContentLoaded', arguments.callee, false);
            fn(); //运行函数
        }, false);
    } else if (document.attachEvent) { //IE浏览器
        document.attachEvent('onreadystatechange', function () {
            if (document.readyState == 'complete') {
                document.detachEvent('onreadystatechange', arguments.callee);
                fn(); //函数运行
            }
        });
    }
}

ready(function(){
    let toc = document.getElementById("toc");
    let title = document.getElementById("title");
    let style = window.getComputedStyle(toc)["display"];
    if(!toc || style == "none"){
        return;
    }
    window.title = true;
    window.addEventListener('scroll',
        function (e) {
            let scroll_height = window.scrollY;
            if (scroll_height > 200 && window.title) {
                window.title = false;
                title.style.bottom = '100%';
                toc.style.top = "1rem";
            } else if (scroll_height <= 200 && !window.title) {
                window.title = true;
                title.removeAttribute("style");
                toc.removeAttribute("style");
            }
        }
    );
})

中间遇到absURL这个函数,功能作用如下:

{{ "mystyle.css" | absURL }} → "https://example.com/hugo/mystyle.css"
{{ "mystyle.css" | relURL }} → "/hugo/mystyle.css"
{{ "http://gohugo.io/" | relURL }} →  "http://gohugo.io/"
{{ "http://gohugo.io/" | absURL }} →  "http://gohugo.io/"

sidebar.html文件做修改,TableOfContents就是toc的内容:

<aside class="sidebar">
  <div id = "title" class="container sidebar-sticky">
    <div class="sidebar-about">
      <a href="/">
        {{if not .IsPage}}
        <h1 class="title">{{ .Site.Title }}</h1>
        {{else}}
        <p class="title">{{ .Site.Title }}</p>
        {{end}}
      </a>
      <p class="lead">
        {{ with .Site.Params.description }}
        {{.}}
        {{end}}
      </p>
    </div>

    <nav>
      <ul class="sidebar-nav">
        <li><a href="/">Home</a> </li>
        {{ range .Site.Menus.main -}}
        <li><a href="{{.URL | absURL }}"> {{ .Name }} </a></li>
        {{- end }}
      </ul>
    </nav>

    <p>&copy; 2017 - {{ now.Format "2006"}} {{.Site.Params.copyright}}. </p>

  </div>
  {{if eq .Section .Site.Params.PostDir}}
  <script defer = "defer" src="/js/toc.js"></script>
  <div id = "toc" class="container sidebar-toc">
    {{ .TableOfContents }}
  </div>
  {{end}}
</aside>

改变标题级数可以在congfig.tml文件上做修改:

[markup]
  [markup.tableOfContents]
    endLevel = 3
    startLevel = 1 #表示从一级目录开始

0x04 添加归档功能(Archives)

_default目录下添加archives.html 文件:

{{ define "main" -}}
<div class="post">
  <h1>{{ .Title }}</h1>
  {{ range (.Site.RegularPages.GroupByDate "2006") }}
  <h3>{{ .Key }}</h3>

  <ul class="archive-list">
    {{ range (where .Pages "Type" "posts") }}
    <li>
      {{ .PublishDate.Format "2006-01-02" }}
      ->
      <a href="{{ .RelPermalink }}">{{ .Title }}</a>
    </li>
    {{ end }}
  </ul>
  {{ end }}
</div>

{{ end }}

config.toml文件下添加以下内容,weight代表权重,越小越靠前:

[Menus]
  main = [
      {Name = "Archives",weight = 1, URL = "archives"}
]

在博客主目录的content目录下新建文件``archives.md`:

---
title: "Archives"
date: 2019-05-28
layout: "archives"
---