Installation process

  1. First of all, installing Hugo is required. Installing Hugo needs to use a package management tool. For the Windows system, I recommend using Scoop. Here introduced how to install Scoop.
  2. Hogo’s tutorial introduces how to create a project. Among them, Step2 (.yml’s config file) and Step3 (download theme) should be configured according to the guide of Papermod.

File introduction

  • content: used to put blog content
  • data: don’t care
  • layouts: custom HTML
  • public: project export file
  • resources: custom CSS and JavaScript
  • Static: storage pictures
  • themes: theme

Files inside themes/Papermodare the relevant code of PaperMod. The main directory is:

  • assets: CSS and JavaScript code of Papermod
  • layouts: HTML of Papermod

Config.yml

Here is my configuration file:

baseURL: https://kyxie.github.io/
languageCode: en-ca # zh-cn
title: Kunyang's Blog
theme: PaperMod

enableInlineShortcodes: true
enableEmoji: true # allowing using emoji
enableRobotsTXT: true

hasCJKLanguage: true

buildDrafts: false
buildFuture: false
buildExpired: false

#googleAnalytics: UA-123-45

paginate: 15 # articles per page

minify:
    disableXML: true
    # minifyOutput: true

permalinks:
    post: "/:title/"
    # post: "/:year/:month/:day/:title/"

defaultContentLanguage: en # prefer language
defaultContentLanguageInSubdir: true

languages:
    en:
        languageName: "English🇨🇦"
        contentDir: content/English
        weight: 1
        profileMode:
            enabled: true
            title: Kyrie Xie
            subtitle: "Welcome to my site!"
            # imageUrl: "Avatar.png"
            imageUrl: "Selfie.png"
            imageTitle: Selfie
            imageWidth: 150
            imageHeight: 150
            buttons:
                - name: About
                  url: about
                - name: Project
                  url: projects
                - name: Resume
                  url: resume.pdf

        menu:
            main:
                - identifier: About
                  name: About
                  url: about
                  weight: 1
                - identifier: Projects
                  name: Project
                  url: projects
                  weight: 2
                - identifier: Resume
                  name: Resume
                  url: resume.pdf
                  weight: 3
                - identifier: Blog
                  name: Blogs
                  url: blog
                  weight: 4
                - identifier: Search
                  name: Search
                  url: search
                  weight: 5

    zh:
        languageName: "中文🇨🇳"
        contentDir: content/Chinese
        weight: 2
        profileMode:
            enabled: true
            title: 谢坤洋
            subtitle: "欢迎来到我的网站!"
            # imageUrl: "Avatar.png"
            imageUrl: "Selfie.png"
            imageTitle: Selfie
            imageWidth: 150
            imageHeight: 150
            buttons:
                - name: 关于
                  url: about
                - name: 博客
                  url: blog
                - name: 简历
                  url: resume.pdf

        menu:
            main:
                - identifier: About
                  name: 关于
                  url: about
                  weight: 1
                - identifier: Projects
                  name: 项目
                  url: projects
                  weight: 2
                - identifier: Resume
                  name: 简历
                  url: resume.pdf
                  weight: 3
                - identifier: Blog
                  name: 博客
                  url: blog
                  weight: 4
                - identifier: Comments
                  name: 留言板
                  url: comment/comments
                  weight: 5
                - identifier: Links
                  name: 友链
                  url: links
                  weight: 6
                - identifier: Search
                  name: 搜索
                  url: search
                  weight: 7

outputs:
    home:
        - HTML
        - RSS
        - JSON

params:
    env: production # to enable google analytics, opengraph, twitter-cards and schema.
    title: Kyrie
    author: Kyrie

    defaultTheme: dark # defaultTheme: light or dark
    disableThemeToggle: false
    DateFormat: "2006-01-02"
    ShowShareButtons: true
    ShowReadingTime: true
    # disableSpecialistPost: true
    disableScrollToTop: false
    displayFullLangName: true
    ShowPostNavLinks: true
    ShowBreadCrumbs: true
    ShowCodeCopyButtons: true
    hideFooter: false # hide foot
    ShowWordCounts: true
    VisitCount: true

    ShowLastMod: true

    ShowToc: true
    TocOpen: true

    comments: true

    socialIcons:
        - name: instagram
          url: "https://www.instagram.com/_kyxie/"
        - name: github
          url: "https://github.com/kyxie"
        - name: linkedin
          url: "https://www.linkedin.com/in/kunyang-kyrie-xie-557270194/"
        # - name: qq
        #   url: "qq.jpg"
        - name: wechat
          url: "wechat.jpg"
        - name: weibo
          url: "https://weibo.com/u/5687393723"
        - name: bilibili
          url: "https://space.bilibili.com/156752850?spm_id_from=333.1007.0.0"
        - name: strava
          url: "https://www.strava.com/athletes/62343657"
        - name: email
          url: "mailto:kyriexie@outlook.com"

    assets:
        favicon: "k-48.png"
        favicon16x16: "k-48.png"
        favicon32x32: "k-48.png"
        apple_touch_icon: "k-48.png"
        safari_pinned_tab: "k-48.png"

    label:
        text: "Home"

    fuseOpts:
        isCaseSensitive: false
        shouldSort: true
        location: 0
        distance: 1000
        threshold: 1
        minMatchCharLength: 0
        keys: ["title", "permalink", "summary"]

    twikoo:
        version: 1.4.11

taxonomies:
    category: categories
    tag: tags
    series: series

markup:
    goldmark:
        renderer:
            unsafe: true
    highlight:
        # anchorLineNos: true
        codeFences: true
        guessSyntax: true
        lineNos: true
        # noClasses: false
        style: monokai
        lineNos: false

privacy:
    vimeo:
        disabled: false
        simple: true

    twitter:
        disabled: false
        enableDNT: true
        simple: true

    instagram:
        disabled: false
        simple: true

    youtube:
        disabled: false
        privacyEnhanced: true

services:
    instagram:
        disableInlineCSS: true
    twitter:
        disableInlineCSS: true

Create an article

Enter the hugo new article name.md to create a Markdown file under thecontent folder. The article head information can modify the attributes of this article.

YAML Front Matter

Here is my yaml front matter file, for details: Front Matter | Hugo (gohugo.io)

---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
lastmod: {{ .Date }}
author: ["Kyrie"]
categories: 
- categorie 1
- categorie 2
tags: 
- tag 1
- tag 2
description: ""
weight: # 1 means pin the article, sort articles according to this number
slug: ""
draft: false # draft or not
comments: true
showToc: true # show contents
TocOpen: true # open contents automantically
hidemeta: false # hide information (author, create date, etc.)
disableShare: true	# do not show share button
showbreadcrumbs: true # show current path
cover:
    image: ""
    caption: ""
    alt: ""
    relative: false
---

Local preview

  1. Enter the hugo server -d in the terminal. It is recommended to create a newly created .bat file to execute this instruction.
  2. After starting the server, open the browser, and the local preview URL is localhost: 1313.

Website deployment

I use GitHub Page.

  1. Create a repository in GitHub, the name is yourname.github.io.
  2. When we preview the local preview is okay, enter hugo -f --cleanDestinationDir in the terminal, and the output file will be generated under the public folder.
  3. We use the public folder as a local repository for GitHub Page. Each time the output file is generated, it is pushed to Github, and Github Page will automatically deploy it.

Multi-language

  • If we want to use multi-language (Chinese and English as an example), we need to prepare two folders under the content folder, such asChinese and English, one in Chinese and the other in English.
  • The following modification is needed in config.yml:
defaultContentLanguage: en
defaultContentLanguageInSubdir: true

languages:
    en:
        languageName: "English"
        contentDir: content/English
    zh:
    	languageName: "中文"
        contentDir: content/Chinese

Translate markdown files using this tool.

Search function

  • Create search.md (hugo new search.md) under the folder of Chinese and English, and modify the file header:
title: "Search"
date: ...
draft: false
layout: search
  • Add to config.yml:
menu:
	main:
		-identifier: Search
		name: Search
		url: search
		weight: ...

Hover

It is mainly modified in the themes/Papermod/assets/css/common/header.css.

  • Home button hover:
.logo a:hover {
    transition: 0.15s;
    color: grey;
}
  • Social media hover:
svg:hover {
    transition: 0.15s;
}

.social-icons a:nth-child(1) svg:hover{
    color: #C84370 !important;
}

.social-icons a:nth-child(2) svg:hover {
    color: grey !important;
}

...

nth-child can set the hover color of each icon.

  • Night mode and day mode hover:
#moon:hover {
    transition: 0.15s;
    color: deepskyblue;
}

#sun:hover {
    transition: 0.15s;
    color: gold;
}
  • Hover of links in menu:
#menu a:hover {
    transition: 0.15s;
    color: grey;
}
  • Button hover:

Modified in the themes/Papermod/assets/css/common/profile-mode.css:

.button:hover {
    -webkit-transform: scale(1.1);
    -moz-transform: scale(1.1);
    -ms-transform: scale(1.1);
    -o-transform: scale(1.1);
    /* box-shadow: 0 0 0 1px grey; */
    transform: scale(1.1) translateZ(0) translate3d(0, 0, 0) rotate(0.01deg);
}

Custom social media icon

  1. Use SVG icons to make websites, such as icons8, find the icons we need, such as WeChat.
  2. You can use Stroke on the left menu bar to adjust the thickness of the lines.
  3. Click download,SVG Embed, the size of the custom icon is 24*24, and then click copy HTML.
  4. Paste the replicated HTML in the themes/Papermod/layouts/partials/svg.html.
  5. You need to modify it to fill=currentColor stroke=currentColor to adapt to the day and night switch.
  6. WeChat and Weibo icons:
{{- else if (eq $icon_name "wechat") -}}
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="24" height="24" viewBox="0 0 50 50">
    <g fill="currentColor" stroke="currentColor" stroke-width="2">
        <path
            d="M 19 6 C 9.746094 6 2 12.359375 2 20.5 C 2 24.894531 4.292969 28.679688 7.835938 31.324219 L 5.179688 39.304688 L 13.472656 34.167969 C 15.1875 34.707031 17.082031 35 19 35 C 19.746094 35 20.472656 34.945313 21.195313 34.863281 C 23.378906 39.105469 28.328125 42 34 42 C 35.722656 42 37.316406 41.675781 38.796875 41.234375 L 45.644531 45.066406 L 43.734375 38.515625 C 46.3125 36.375 48 33.394531 48 30 C 48 23.789063 42.597656 18.835938 35.75 18.105469 C 34.398438 11.125 27.324219 6 19 6 Z M 19 8 C 26.308594 8 32.328125 12.351563 33.703125 18.011719 C 26.183594 18.148438 20 23.355469 20 30 C 20 31.019531 20.160156 32.003906 20.4375 32.941406 C 19.964844 32.980469 19.484375 33 19 33 C 17.101563 33 15.199219 32.710938 13.632813 32.15625 L 13.183594 32 L 8.820313 34.699219 L 10.1875 30.59375 L 9.5625 30.171875 C 6.082031 27.820313 4 24.445313 4 20.5 C 4 13.640625 10.65625 8 19 8 Z M 13 14 C 11.898438 14 11 14.898438 11 16 C 11 17.101563 11.898438 18 13 18 C 14.101563 18 15 17.101563 15 16 C 15 14.898438 14.101563 14 13 14 Z M 25 14 C 23.898438 14 23 14.898438 23 16 C 23 17.101563 23.898438 18 25 18 C 26.101563 18 27 17.101563 27 16 C 27 14.898438 26.101563 14 25 14 Z M 34 20 C 40.746094 20 46 24.535156 46 30 C 46 32.957031 44.492188 35.550781 42.003906 37.394531 L 41.445313 37.8125 L 42.355469 40.933594 L 39.105469 39.109375 L 38.683594 39.25 C 37.285156 39.71875 35.6875 40 34 40 C 27.253906 40 22 35.464844 22 30 C 22 24.535156 27.253906 20 34 20 Z M 29.5 26 C 28.699219 26 28 26.699219 28 27.5 C 28 28.300781 28.699219 29 29.5 29 C 30.300781 29 31 28.300781 31 27.5 C 31 26.699219 30.300781 26 29.5 26 Z M 38.5 26 C 37.699219 26 37 26.699219 37 27.5 C 37 28.300781 37.699219 29 38.5 29 C 39.300781 29 40 28.300781 40 27.5 C 40 26.699219 39.300781 26 38.5 26 Z">
        </path>
    </g>
</svg>
{{- else if (eq $icon_name "weibo") -}}
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="24" height="24" viewBox="0 0 172 172">
    <g fill="currentColor" stroke="currentColor" stroke-width="4">
        <path
            d="M120.4,20.64c-2.67406,0 -5.25406,0.26875 -7.74,0.71219c-1.86781,0.3225 -3.1175,2.10969 -2.795,3.9775c0.3225,1.88125 2.10969,3.13094 3.9775,2.80844c2.17688,-0.38969 4.35375,-0.61813 6.5575,-0.61813c20.93563,0 37.84,16.90438 37.84,37.84c0,4.52844 -0.83312,8.85531 -2.31125,12.91344c-0.45687,1.16906 -0.25531,2.48594 0.5375,3.45344c0.80625,0.9675 2.05594,1.42437 3.29219,1.19594c1.23625,-0.22844 2.24406,-1.11531 2.63375,-2.29781c1.73344,-4.75687 2.72781,-9.87656 2.72781,-15.265c0,-24.65781 -20.06219,-44.72 -44.72,-44.72zM120.4,41.28c-1.46469,0 -2.84875,0.14781 -4.16562,0.37625c-1.86781,0.33594 -3.13094,2.10969 -2.795,3.99094c0.3225,1.86781 2.10969,3.1175 3.9775,2.795c1.00781,-0.17469 2.00219,-0.28219 2.98312,-0.28219c9.54063,0 17.2,7.65938 17.2,17.2c0,2.05594 -0.37625,4.01781 -1.06156,5.87219c-0.645,1.78719 0.28219,3.7625 2.06938,4.4075c1.78719,0.645 3.7625,-0.26875 4.4075,-2.05594c0.92719,-2.55312 1.46469,-5.32125 1.46469,-8.22375c0,-13.26281 -10.81719,-24.08 -24.08,-24.08zM72.46844,42.6775c-11.04562,0 -27.50656,8.66719 -42.18031,23.07219c-14.76781,14.76781 -23.40813,30.24781 -23.40813,43.57781c0,25.9075 33.12344,41.3875 65.88406,41.3875c42.47594,0 70.90969,-24.46969 70.90969,-43.91375c0,-11.87875 -10.07812,-18.35562 -19.08125,-21.23125c-2.15,-0.72562 -3.60125,-1.08844 -2.52625,-3.96406c0.72563,-1.73344 1.77375,-5.01219 1.77375,-9.36594c0,-4.945 -3.44,-9.23156 -10.32,-9.9975c-0.79281,-0.08062 -2.13656,-0.14781 -3.82969,-0.14781c-5.6975,0 -15.48,0.71219 -22.52125,3.66844c0,0 -1.38406,0.57781 -2.49938,0.57781c-1.00781,0 -1.80062,-0.48375 -1.11531,-2.37844c2.52625,-7.91469 2.16344,-14.39156 -1.80063,-18.00625c-2.23062,-2.23062 -5.42875,-3.27875 -9.28531,-3.27875zM72.46844,49.5575c1.43781,0 3.37281,0.215 4.43438,1.26313l0.1075,0.12094l0.12094,0.1075c1.54531,1.41094 1.51844,5.61687 -0.09406,10.72312c-1.38406,3.99094 -0.09406,6.75906 0.81969,8.04906c1.51844,2.16344 4.00437,3.39969 6.81281,3.39969c2.28438,0 4.39406,-0.79281 5.14656,-1.11531c5.50938,-2.31125 13.88094,-3.13094 19.87406,-3.13094c1.53187,0 2.60687,0.05375 3.07719,0.1075c2.78156,0.30906 4.1925,1.37063 4.1925,3.15781c0,3.23844 -0.77937,5.61688 -1.23625,6.73219l-0.05375,0.1075l-0.04031,0.09406c-1.075,2.88906 -1.06156,5.50938 0.04031,7.80719c1.62594,3.39969 4.82406,4.46125 6.54406,5.03906l0.28219,0.09406c5.34813,1.70656 14.2975,5.88562 14.2975,14.68719c0,7.90125 -6.81281,17.65688 -18.90656,25.16844c4.77031,-5.54969 7.47125,-12.05344 7.47125,-19.05437c0,-21.01625 -24.37562,-37.47719 -55.48344,-37.47719c-31.10781,0 -55.47,16.46094 -55.47,37.47719c0,0.645 0.01344,1.27656 0.05375,1.90812c-0.45687,-1.76031 -0.69875,-3.60125 -0.69875,-5.49594c0,-11.16656 7.59219,-24.91312 21.33875,-38.65969c14.86188,-14.59313 29.48188,-21.11031 37.36969,-21.11031zM69.875,82.33156c26.84813,0 48.60344,13.69281 48.60344,30.59719c0,16.89094 -21.75531,30.58375 -48.60344,30.58375c-26.83469,0 -48.59,-13.69281 -48.59,-30.58375c0,-16.90437 21.75531,-30.59719 48.59,-30.59719zM66.27375,89.52063c-10.38719,0.08062 -20.47875,5.76469 -24.85937,14.52594c-5.40188,11.13969 -0.36281,23.38125 12.59094,27.33187c12.95375,4.31344 28.42031,-2.16344 33.82219,-14.02875c5.38844,-11.5025 -1.43781,-23.73062 -14.39156,-26.95562c-2.365,-0.61813 -4.77031,-0.88688 -7.16219,-0.87344zM71.63531,104.06c1.98875,0 3.60125,1.59906 3.60125,3.58781c0,1.98875 -1.6125,3.60125 -3.60125,3.60125c-1.98875,0 -3.60125,-1.6125 -3.60125,-3.60125c0,-1.98875 1.6125,-3.58781 3.60125,-3.58781zM56.47781,107.64781c1.12875,0.01344 2.2575,0.18812 3.31906,0.55094c4.60906,1.46469 6.02,5.83188 3.18469,9.47344c-2.4725,3.64156 -8.12969,5.45563 -12.38938,3.64156c-4.23281,-1.81406 -5.29437,-6.19469 -2.82187,-9.46c1.85437,-2.74125 5.30781,-4.24625 8.7075,-4.20594z">
        </path>
    </g>
    <path d="" fill="none"></path>
</svg>

Directory column placed side

We can place the directory column to the side, we need to do some modification.

Rewrite layouts/partials/toc.html:

{{- $headers := findRE "<h[1-6].*?>(.|\n])+?</h[1-6]>" .Content -}}
{{- $has_headers := ge (len $headers) 1 -}}
{{- if $has_headers -}}
<aside id="toc-container" class="toc-container wide">
    <div class="toc">
        <details {{if (.Param "TocOpen") }} open{{ end }}>
            <summary accesskey="c" title="(Alt + C)">
                <span class="details">{{- i18n "toc" | default "Table of Contents" }}</span>
            </summary>

            <div class="inner">
                {{- $largest := 6 -}}
                {{- range $headers -}}
                {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}}
                {{- $headerLevel := len (seq $headerLevel) -}}
                {{- if lt $headerLevel $largest -}}
                {{- $largest = $headerLevel -}}
                {{- end -}}
                {{- end -}}

                {{- $firstHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers 0) 1) 0)) -}}

                {{- $.Scratch.Set "bareul" slice -}}
                <ul>
                    {{- range seq (sub $firstHeaderLevel $largest) -}}
                    <ul>
                        {{- $.Scratch.Add "bareul" (sub (add $largest .) 1) -}}
                        {{- end -}}
                        {{- range $i, $header := $headers -}}
                        {{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}}
                        {{- $headerLevel := len (seq $headerLevel) -}}

                        {{/* get id="xyz" */}}
                        {{- $id := index (findRE "(id=\"(.*?)\")" $header 9) 0 }}

                        {{- /* strip id="" to leave xyz, no way to get regex capturing groups in hugo */ -}}
                        {{- $cleanedID := replace (replace $id "id=\"" "") "\"" "" }}
                        {{- $header := replaceRE "<h[1-6].*?>((.|\n])+?)</h[1-6]>" "$1" $header -}}

                        {{- if ne $i 0 -}}
                        {{- $prevHeaderLevel := index (findRE "[1-6]" (index $headers (sub $i 1)) 1) 0 -}}
                        {{- $prevHeaderLevel := len (seq $prevHeaderLevel) -}}
                        {{- if gt $headerLevel $prevHeaderLevel -}}
                        {{- range seq $prevHeaderLevel (sub $headerLevel 1) -}}
                        <ul>
                            {{/* the first should not be recorded */}}
                            {{- if ne $prevHeaderLevel . -}}
                            {{- $.Scratch.Add "bareul" . -}}
                            {{- end -}}
                            {{- end -}}
                            {{- else -}}
                            </li>
                            {{- if lt $headerLevel $prevHeaderLevel -}}
                            {{- range seq (sub $prevHeaderLevel 1) -1 $headerLevel -}}
                            {{- if in ($.Scratch.Get "bareul") . -}}
                        </ul>
                        {{/* manually do pop item */}}
                        {{- $tmp := $.Scratch.Get "bareul" -}}
                        {{- $.Scratch.Delete "bareul" -}}
                        {{- $.Scratch.Set "bareul" slice}}
                        {{- range seq (sub (len $tmp) 1) -}}
                        {{- $.Scratch.Add "bareul" (index $tmp (sub . 1)) -}}
                        {{- end -}}
                        {{- else -}}
                    </ul>
                    </li>
                    {{- end -}}
                    {{- end -}}
                    {{- end -}}
                    {{- end }}
                    <li>
                        <a href="#{{- $cleanedID -}}" aria-label="{{- $header | plainify -}}">{{- $header | safeHTML -}}</a>
                        {{- else }}
                    <li>
                        <a href="#{{- $cleanedID -}}" aria-label="{{- $header | plainify -}}">{{- $header | safeHTML -}}</a>
                        {{- end -}}
                        {{- end -}}
                        <!-- {{- $firstHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers 0) 1) 0)) -}} -->
                        {{- $firstHeaderLevel := $largest }}
                        {{- $lastHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers (sub (len $headers) 1)) 1) 0)) }}
                    </li>
                    {{- range seq (sub $lastHeaderLevel $firstHeaderLevel) -}}
                    {{- if in ($.Scratch.Get "bareul") (add . $firstHeaderLevel) }}
                </ul>
                {{- else }}
                </ul>
                </li>
                {{- end -}}
                {{- end }}
                </ul>
            </div>
        </details>
    </div>
</aside>
<script>
    let activeElement;
    let elements;
    window.addEventListener('DOMContentLoaded', function (event) {
        checkTocPosition();

        elements = document.querySelectorAll('h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]');
         // Make the first header active
         activeElement = elements[0];
         const id = encodeURI(activeElement.getAttribute('id')).toLowerCase();
         document.querySelector(`.inner ul li a[href="#${id}"]`).classList.add('active');
     }, false);

    window.addEventListener('resize', function(event) {
        checkTocPosition();
    }, false);

    window.addEventListener('scroll', () => {
        // Check if there is an object in the top half of the screen or keep the last item active
        activeElement = Array.from(elements).find((element) => {
            if ((getOffsetTop(element) - window.pageYOffset) > 0 && 
                (getOffsetTop(element) - window.pageYOffset) < window.innerHeight/2) {
                return element;
            }
        }) || activeElement

        elements.forEach(element => {
             const id = encodeURI(element.getAttribute('id')).toLowerCase();
             if (element === activeElement){
                 document.querySelector(`.inner ul li a[href="#${id}"]`).classList.add('active');
             } else {
                 document.querySelector(`.inner ul li a[href="#${id}"]`).classList.remove('active');
             }
         })
     }, false);

    const main = parseInt(getComputedStyle(document.body).getPropertyValue('--article-width'), 10);
    const toc = parseInt(getComputedStyle(document.body).getPropertyValue('--toc-width'), 10);
    const gap = parseInt(getComputedStyle(document.body).getPropertyValue('--gap'), 10);

    function checkTocPosition() {
        const width = document.body.scrollWidth;

        if (width - main - (toc * 2) - (gap * 4) > 0) {
            document.getElementById("toc-container").classList.add("wide");
        } else {
            document.getElementById("toc-container").classList.remove("wide");
        }
    }

    function getOffsetTop(element) {
        if (!element.getClientRects().length) {
            return 0;
        }
        let rect = element.getBoundingClientRect();
        let win = element.ownerDocument.defaultView;
        return rect.top + win.pageYOffset;   
    }
</script>
{{- end }}

At assets/css/extended/blank.css:

:root {
    --nav-width: 1380px;
    --article-width: 650px;
    --toc-width: 300px;
}

.toc {
    margin: 0 2px 40px 2px;
    border: 1px solid var(--border);
    background: var(--entry);
    border-radius: var(--radius);
    padding: 0.4em;
}

.toc-container.wide {
    position: absolute;
    height: 100%;
    border-right: 1px solid var(--border);
    left: calc((var(--toc-width) + var(--gap)) * -1);
    top: calc(var(--gap) * 2);
    width: var(--toc-width);
}

.wide .toc {
    position: sticky;
    top: var(--gap);
    border: unset;
    background: unset;
    border-radius: unset;
    width: 100%;
    margin: 0 2px 40px 2px;
}

.toc details summary {
    cursor: zoom-in;
    margin-inline-start: 20px;
    padding: 12px 0;
}

.toc details[open] summary {
    font-weight: 500;
}

.toc-container.wide .toc .inner {
    margin: 0;
}

.active {
    font-size: 110%;
    font-weight: 600;
}

.toc ul {
    list-style-type: circle;
}

.toc .inner {
    margin: 0 0 0 20px;
    padding: 0px 15px 15px 20px;
    font-size: 16px;
}

.toc li ul {
    margin-inline-start: calc(var(--gap) * 0.5);
    list-style-type: none;
}

.toc li {
    list-style: none;
    font-size: 0.95rem;
    padding-bottom: 5px;
}

.toc li a:hover {
    color: var(--secondary);
}

Markdown rendering style

For details: 折腾 Hugo & PaperMod 主题 - Dvel’s Blog

Traffic Statistics

Here I use busuanzi and modify it in the themes/Papermod/layouts/partials/svg.html:

{{- if not (.Param "hideFooter") }}
<footer class="footer">
    {{- if site.Copyright }}
		...
    {{- end }}
    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span id="busuanzi_container">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
        Visitors: <span id="busuanzi_value_site_uv"></span>
        Views: <span id="busuanzi_value_site_pv"></span>
    </span>
</footer>
{{- end }}

Insert Bilibili, YouTube video or PPT

For details: Hugo博客自定义shortcodes | Sulv’s Blog (sulvblog.cn)

Insert music player

For details: Hugo插入音乐播放器 Hidden lyrics: lrc-type = 0

Modify the global font

First find your favorite font, and then you can check the font in Google Fonts. My current articles font is Josefin Sans. Google Fonts will generate HTML and CSS, insert HTML into themes/PaperMod/layouts/partials/extend_head.html, and insert css to themes/papermod/assets/extended/blank.css.

body {
    font-family: 'Josefin Sans', sans-serif;
    font-size: 1rem;
    line-height: 1.5;
    margin: 0;
}

Modify code font

Similar to global fonts, the difference is differently inserted by CSS code.The font I use is Ubuntu Mono.

.post-content pre, code {
    font-family: 'Ubuntu Mono', monospace;
    max-height: 40rem;
}

Comment function

For details: Hugo博客添加Twikoo评论 | Sulv’s Blog (sulvblog.cn)

Outlook email configuration

For details: 关于邮箱配置的问题? · Discussion #249 · imaegoo/twikoo (github.com)

Custom mailbox reply template

For details: 自定义Twikoo邮件通知模板 | Guo Le’s Blog

Code highlight

Modify in two places One is themes/PaperMod/assets/css/common/post-single.css:

.post-content pre code {
    display: block;
    margin: auto 0;
    padding: 10px;
    /* Color of main code */
    color: #abb2bf;
    font-weight: 200;
    overflow-x: auto;
    word-break: break-all;
}

The other is themes/PaperMod/assets/css/hljs/an-old-hope.min.css, here is my example:

/* Comment */
.hljs-comment,
.hljs-quote {
    font-weight: 200;
    color: #7f848e;
}

.hljs-deletion,
/* html index */
.hljs-name,
.hljs-regexp,
.hljs-tag {
    font-weight: 200;
    color: #e06c75;
}

/* html attribute */
.hljs-tag {
    font-weight: 200;
    color: #d19a66;
}

/* css class name */
.hljs-template-variable,
.hljs-variable,
.hljs-selector-class,
.hljs-selector-id {
    font-weight: 200;
    color: #a9b600;
}

/* built in function */
.hljs-built_in,
.hljs-builtin-name {
    font-weight: 200;
    color: #56b6c2;
}

/* function input */
.hljs-params {
    font-weight: 200;
    color: #e5c07b;
}

/* number */
.hljs-number {
    font-weight: 200;
    color: #d19a66;
}

/* css attribute */
.hljs-attribute {
    font-weight: 200;
    color: #ee7c2b;
}

/* string */
.hljs-addition,
.hljs-bullet,
.hljs-symbol,
.hljs-string {
    font-weight: 200;
    color: #98c379;
}

/* function name */
.hljs-section,
.hljs-title {
    font-weight: 200;
    color: #56b6c2;
}

/* keyword */
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-link,
.hljs-meta,
.hljs-type {
    font-weight: 200;
    color: #c678dd;
}

.hljs {
    display: block;
    overflow-x: auto;
    background: #1c1d21;
    color: #c0c5ce;
    padding: 0.5em;
}

.hljs-emphasis {
    font-style: italic;
}

.hljs-strong {
    font-weight: 700;
}

/* 选中时的背景颜色 */
.hljs ::selection,
.hljs::selection {
    background-color: #3d4556;
}

Code border round corner

themes/PaperMod/assets/css/common/post-single.css:

.post-content .highlight pre {
    background-color: var(--theme) !important;
    margin: 0;
}

For details: Hugo博客添加友链 | Sulv’s Blog (sulvblog.cn)