引子

前段时间对博客进行了整理和翻新,趁着记忆还没完全模糊,将搭建博客的细节记录下来。个人而言,对目前博客的各项功能以及美观度还是比较满意的,而这些背后也付出了一定的努力,希望也对其他想折腾博客的人有些许帮助,那样就更好了!也作为博客分类「折腾」的第一篇,送给自己~

注意:博客的主题是基于 Hugo 的 PaperMod 进行魔改,故而诸多相关细节未必适用于其他博客框架,请阅读理解后进行使用。另外,本博客相关源码也放在此,方便进行查阅

This is the demo of my improved PaperMod theme. You can visit the introduction: https://yunpengtai.top/posts/hello-world/
HTML

关于本文涉及的一些用法示例,可以参见本篇文章的源码

基础知识

这里主要介绍 Hugo 主题相关的基础知识,比如文件夹代表的意思,我使用的 Hugo 版本以及常用命令等,有基础的读者应直接跳至下一节进行阅读

组成

开始之前,先说明一个比较重要的事情,你会发现 layouts 和 assets 在 themes 下某个主题里也有,不要在主题里进行修改,否则当你主题更新后,就比较麻烦,正确做法应该是在 themes 同级目录创建

以下即为一个 Hugo 主题常见的组成结构:

|—— assets # 放置 css 和 js
    |—— css
    |—— js
|—— content # 放置网站内容,比如 posts,或者 friends.md
    |—— posts
        |—— hello-world.md
    friends.md # 友链内容
|—— data # 我是只放了 SVG.toml 文件
|—— layouts # 控制网站相关的布局
    |—— _default # 主题内置的布局,如 single.html 代表一个帖子的布局
    |—— partials # 放置你个人魔改的部件
        |—— extend_footer.html # 代码会添加到原网站的 footer 里
        |—— extend_head.html # 代码会添加到原网站的 head 里
    |—— shortcodes # 一些好玩的 shortcodes 命令
|—— public # 渲染后的纯 HTML 代码,刚下载未渲染不会有该目录
|—— resources # 一般不用管
|—— static # 网站的字体以及 icon 放置目录
    |—— fonts
    favicon.ico
|—— themes
    |—— PaperMod
config.yaml # 网站的配置文件

content 目录下的路径关系,即为网站上的链接顺序,比如 hello-world.md 访问链接便为:域名/posts/hello-world/,而 friends.md 便为 域名/friends BTW,如果想在文章中引用博客内容,可以省去域名[hello-world](/posts/hello-world)

另外,Hugo 新手可能不知道 shortcodes 是啥意思,可以理解为一种快捷指令,具体的意思也可去 Hugo 官网 查看

config.yaml 里面可以放置全局参数以及 menu 等信息,根据你所使用的主题文档进行修改即可,这里不加以讨论

调试和发布

我的 Hugo 一直是使用老版本:

hugo version
# hugo v0.117.0-b2f0696cad918fb61420a6aff173eb36662b406e linux/amd64 BuildDate=2023-08-07T12:49:48Z VendorInfo=gohugoio

Hugo 常用的也就两个命令:

hugo server # 进行本地调试
hugo # 正式渲染,结果在 public,将 public 上传至支持静态站的地方即可发布

另外关于 Hugo 中常见的变量以及支持的方法,也应该去官网查看更详细的记录,还有时常在 Hugo HTML 中出现的,类似如下内容是属于「Go」的模板函数,不只是 Go,如果有任何疑问,查看官网 doc 永远是第一选择

{{ if or .Params.math .Site.Params.math }}
...
{{ end }}

有了如上的基础知识后,我们可以来愉快的进行精装修了

数学公式

$a=b$ 这是行内公式

这是行间公式 $$ e=mc^2 $$

对于写技术 blog 的同志们来说,数学公式的适配几乎是必须的,然而很多主题未对数学公式进行适配,或者只是比较随意的适配(有些情况还是不会 work),我使用的这个主题作者就在 GitHub issues 里贴了所谓的实现方案,内容如下:

{{ if or .Params.math .Site.Params.math }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js" integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js" integrity="sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa" crossorigin="anonymous"
    onload="renderMathInElement(document.body);"></script>
{{ end }}

看似基本的公式可以正常显示,然而,当公式复杂起来,上述方案就不会 work 了,比如:

$$
\frac{\partial E(\boldsymbol{w})}{\partial z_j} = \sum\limits_{k}\frac{\partial E(\boldsymbol{w})}{\partial y_{k}}\frac{\partial y_k}{\partial z_{j}}= \sum\limits_{k} (y_{k}- \hat{y}_{k}) w_{kj}^{(2)} \tag{5.11}
$$

有了可以渲染数学元素的工具还不够,因为你还需要保证公式的内容并没有进行修改。举个例子,当你想要渲染 a_{1} + b_{1},而 Hugo 可能将下划线渲染成 markdown 的模式:a<em>1 + b</em>1,导致 mathjax 去渲染的时候找不到你原来的公式,进而导致了渲染的失败。解决方案是将带有公式的部分先用代码 block 装饰起来,避免内容被修改,接着再将代码 block 去掉,完整的送给渲染工具 借鉴了谢益辉的相关实现

在 layouts/partials/extend_footer.html 中复制以下 js 代码:

去掉数学公式的代码框 js
<script>
(function() {
  var i, text, code, codes = document.getElementsByTagName('code');
  for (i = 0; i < codes.length;) {
    code = codes[i];
    if (code.parentNode.tagName !== 'PRE' && code.childElementCount === 0) {
      text = code.textContent;
      if (/^\`$[^$`]/.test(text) && /[^`$]\$``$/.test(text)) {$`
        text = text.replace(/^\`$/, '\\(').replace(/\$``$/, '\\)');$`
        code.textContent = text;
      }
      if (/^\\\((.|\s)+\\\)`$/.test(text) || /^\\\[(.|\s)+\\\]$`/.test(text) ||
          /^\`$(.|\s)+\$``$/.test(text) ||$`
          /^\\begin\{([^}]+)\}(.|\s)+\\end\{[^}]+\}`$/.test(text)) {$`
        code.outerHTML = code.innerHTML;  // remove <code></code>
        continue;
      }
    }
    i++;
  }
})();
</script>

接着在 layouts/partials/extend_head.html 中引用 layouts/partials/mathjax.html:由全局和网站变量来共同决定是否进行数学公式渲染 上述文件若是不存在则自己创建

{{ if or .Params.math .Site.Params.math }}
{{- partial "mathjax.html" .}}
{{ end }}

mathjax.html 的内容如下,当然我这里还加了额外的 boldsymbol 包,没有需求的可以去掉

mathjax.html
<script>
  MathJax = {
    loader: { load: ["[tex]/boldsymbol"] },
    tex: {
      inlineMath: [
        ["`$", "$`"],
        ["\\(", "\\)"],
      ],
      displayMath: [
        ["`$$`", "`$$`"],
        ["\\[", "\\]"],
      ],
      processEscapes: true,
      processEnvironments: true,
      tags: "all",
      packages: { "[+]": ["boldsymbol"] },
    },
  };
</script>

<script
  src="https://cdn.jsdelivr.net/npm/[email protected]/es5/tex-chtml-full.js"
  integrity="sha256-kbAFUDxdHwlYv01zraGjvjNZayxKtdoiJ38bDTFJtaQ="
  crossorigin="anonymous"
></script>

至此,数学公式的渲染问题就解决好了,使用时把原本的公式放入 code block 即可:

`$a=b$` 行内公式
以下是行间公式
`$$
e=mc^2
$$`

评论系统

评论系统用过很多,比如用 GitHub 来驱动,或者自部署类比如 Waline,之前一直是用 Waline,有表情包,也支持邮箱通知等。但是,技术 blog 的评论系统怎么能没有「公式的集成」呢?所以我选择了Artalk,支持公式,表情,邮箱通知,自动亮暗模式等,功能很全,作者也在积极更新~

概念上 Artalk 分为前后端以及存储所需要的数据库,先讲前端的配置,创建 layouts/partials/artalk.html,内容如下,因为我需要用到 katex,故而引入了其 css 和 js 相关的文件,读者应根据自己需要进行取舍

末尾处有一个自动设置亮暗的代码,逻辑就是监听负责亮暗主题切换的按钮,从而进行自动亮暗,不同主题的 element id 势必会有些许不同,故而不可照抄~

artalk.html
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/katex.min.css"/>
<script src="https://unpkg.com/[email protected]/dist/katex.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/artalk/2.8.6/Artalk.js"></script>
<script src="https://unpkg.com/@artalk/plugin-katex@latest/dist/artalk-plugin-katex.js"></script>

<div id="Comments"></div>
<script>
  const artalk = Artalk.init({
    el: "#Comments", // 绑定元素的 Selector
    pageKey: "",
    pageTitle: "{{ .Title }}",
    server: "{{ site.Params.artalk.server }}", // 后端地址
    site: "{{ site.Params.artalk.site }}", // 你的站点名
    darkMode: "auto", // 首次打开时自动亮暗模式
    versionCheck: false, // 不提醒需要更新
  });
  document.getElementById("theme-toggle").addEventListener("click", () => {
    document.body.className.includes("dark")
      ? artalk.setDarkMode(!1)
      : artalk.setDarkMode(!0);
  });
</script>

另外,关于停用版本检测,不仅要设置前端的参数,后端的参数也需要设置为 false,具体即为 render 上的 conf.yaml

接着在同级目录中创建 comments.html 来引用即可:

{{ if or .Params.comments .Site.Params.comments }}
{{- partial "artalk.html" .}}
{{ end }}

关于数据库以及后端部署的部署,很大程度得益于这位网友的帖子,重复内容就不多赘述,我选择的是 Neon+Render 来分别部署数据库和后端,关于 Render 部署的详细文件,可以参考这里。这里为表情包多做一条说明,如果是希望网站支持表情包,则在 conf.yaml 中的 emoticons 项中加入表情包的远程链接

emoticons: link_to_artalk.json

关于此文件的具体格式,可以参考我的表情包配置仓库,至此,评论系统集成也已经完毕。当然,本网站的 artalk 看上去可能与你们的有些许不同,比如表情包的大小以及没有头像,我自己又改了一些 CSS 来完成上述目标,创建 assets/css/extended/artalk.css,将 artalk 对应的 CSS 内容复制进去,然后加入以下内容

Artalk css
/* 改变表情包大小 */
img[atk-emoticon] {
  width: 5em;
  height: auto;
  display: initial;
}
/* 下列内容可能存在于原来的 CSS 文件内,请查找后进行修改 */
.atk-comment > .atk-avatar img {
  width: 50px;
  height: 50px;
  border-radius: 3px;
  display: none; /* 移除头像 */
}

至于字体方面,等后面讲网站字体介绍即可,并未加其他特殊设置。关于邮箱通知,你需要去专门进行相关设置,请根据官方文档进行,比较简单,这里进行省略

更好看

这一节主要讲为了博客变得更好看做的改变

字体

我对博客的字体向来是比较挑剔,而且这很影响读者的观感,我比较喜欢霞鹜文楷,这款字体好看而且是开源的。不过该字体可不小,对于个人的轻量级 blog 来说,还是存在着优化的可能性,故而,我在博客上使用的是 woff2 格式文件,大小只有 2 M,直接放到了 static/fonts 目录,然后用 CSS 来控制网站整体的外观即可:

字体 CSS 设置
@font-face {
  font-family: "LXGWWenKaiScreenR";
  src: url("/fonts/lxgwwenkaiscreen.subset.v1.235.standard.woff2");
}

body {
  font-family: -apple-system, BlinkMacSystemFont, segoe ui, Roboto, Oxygen,
    Ubuntu, Cantarell, "LXGWWenKaiScreenR", open sans, helvetica neue,
    sans-serif;
  font-size: 16px;
  line-height: 1.6;
  word-break: break-word;
  background: var(--theme);
  font-display: swap;
}

code {
  font-family: "Consolas", "LXGWWenKaiScreenR";
}

代码渲染

代码渲染的主题其实也是见仁见智吧,我个人是选择了atom-one-dark/light

这里提供一下修改方法,因为我们需要覆盖掉原先主题对于代码渲染的设置,所以在 assets/css/hljs 中创建 an-old-hope.min.css ,注意,必须为该名字,当然如果是 Hugo PaperMod 主题肯定另有不同,然后直接复制相关的 CSS 进去。

这里唯一需要注意的是亮暗模式的设置,对于亮色模式,直接拷贝 light 即可,但对于暗色来说,则需要一些特定的限定:

body.dark {
  .hljs {
    color: #abb2bf;
    background: #282c34;
  }
  ...
}

同时,需要修改亮暗模式下代码框的背景颜色,这里是直接用变量来进行替代

代码 CSS 设置
.post-content code {
  margin: auto 4px;
  padding: 4px 6px;
  font-size: 0.8em;
  line-height: 1.5;
  background: var(--code-bg);
}

.post-content pre code {
  display: block;
  margin: auto 0;
  padding: 10px;
  background: var(--hljs-bg) !important;
  color: var(--content);
  border-radius: var(--radius);
  overflow-x: auto;
  word-break: break-all;
  font-family: "Consolas";
  font-size: 15px;
}

这两个变量进行设置的地方在 assets/css/core/theme-vars.css 这里:

theme-vars.css
/* 省略的内容请拷贝原先主题对应的文件 */
:root {
  ...
  --hljs-bg: #f7f7f7;
  --code-bg: rgb(245, 245, 245);
}

.dark {
  ...
  --hljs-bg: rgb(46, 46, 51);
  --code-bg: rgb(55, 56, 62);
}

表格

对主题自带的表格渲染也进行修改,同时适配亮暗模式,还是需要注意暗色模式下的设置

姓名年龄职业
张三30工程师
李四25设计师
王五35医生

表格 CSS
table {
  border-collapse: collapse;
  display: table;
  margin-bottom: 1rem;
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;

  & thead th {
    vertical-align: bottom;
    border-bottom: 2px solid #dee2e6;
  }
  & td,
  & th {
    vertical-align: top;
    border-top: 1px solid #dee2e6;
    border-bottom: 1px solid #dee2e6;
  }

  & tbody tr:hover {
    background-color: rgba(0, 0, 0, 0.075);
  }

  & tbody tr:nth-of-type(2n + 1) {
    background-color: rgba(0, 0, 0, 0.05);
  }
  & tr:last-of-type {
    vertical-align: bottom;
    border-bottom: 2px solid #dee2e6;
  }
}

.dark table {
  border-collapse: collapse;
  display: table;
  margin-bottom: 1rem;
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;

  & thead th {
    vertical-align: bottom;
    border-bottom: 2px solid var(--code-bg);
  }
  & td,
  & th {
    vertical-align: top;
    border-top: 1px solid var(--code-bg);
    border-bottom: 1px solid var(--code-bg);
  }

  & tbody tr:hover {
    background-color: var(--code-bg);
  }

  & tbody tr:nth-of-type(2n + 1) {
    background-color: var(--code-bg);
  }
  & tr:last-of-type {
    vertical-align: bottom;
    border-bottom: 2px solid var(--code-bg);
  }
}

svg icon

觉得主页上的 icon 不太好看也可以进行修改,修改的方法就是将原来主题中的 layouts/partials/svg.html 拷贝到我们的 partials 目录,然后就选择自己想要的 icon 进行修改,这样就会覆盖了

更便于阅读

这一节主要讲博客为了更方便读者阅读做出的努力

侧边悬浮目录

悬浮目录是比较重要的,原始的目录是固定在文章的顶部,这样不便于读者阅读时对目录有直观的把握,也不利于读者进行快速跳转。

在 assets/css/extended/toc.css 中添加代码即可 借鉴了 sulvblog 的实现

悬浮目录 CSS
:root {
  --article-width: 650px;
  --toc-width: 230px;
}

.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) * 0.9 + 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;
}

.toc .active {
  font-size: 110%;
  font-weight: 600;
  color: #614a85;
  text-decoration: underline;
}

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

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

  /*目录显示高度*/
  max-height: 83vh;
  overflow-y: auto;
}

.toc .inner::-webkit-scrollbar-thumb {
  /*滚动条*/
  background: var(--border);
  border: 7px solid var(--theme);
  border-radius: var(--radius);
}

.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);
}

添加修改时间

原先的主题并没有显示「修改时间」的功能,这对于读者阅读起来并不是好事情,像我阅读时就会关注文章最后一次的修改日期,否则可能会过时

在 layouts/partials/post_meta.html 中加入以下内容即可:

{{- if (.Param "ShowLastMod") -}}
    {{ if ne (.Lastmod.Format "2006-01-02") (.Date.Format "2006-01-02") }}
    {{- `$scratch.Add "meta" (slice (printf "Updated:&nbsp;%s" (.Lastmod.Format (.Site.Params.dateFormat | default "January 2, 2006")))) }}$`
  {{- end -}}
{{- end -}}

然后在具体的帖子里加入 lastmod 和 showLastMod 即可显示出修改的时间了

---
title: 新的主题
date: 2022-06-19 11:10:00 +0800
lastmod: 2024-11-20 18:00:00 +0800
showLastMod: true
...
---

MarginNote

这是示例 这是示例的侧边注解

很多时候想补充说明,或者引用某些内容时,常见的脚注就必须跳转到文章末尾进行阅读,然后读者还需要跳回来,这就十分不方便,而 MarginNote 则并不会有这些问题,借由 MarginNote, 就可以在文章的侧边来显示信息,读者阅读起来也会方便很多 借鉴了 kennethfriedmanscripter

首先来说相关的 CSS,主题的实现也是通过 CSS 来进行实现,以及 sidenote number 的增减,不过有些时候会有 bug,故而,为了方便起见,我索性将 number 变为固定的「#」,显示起来也比较美观

MarginNote CSS
.sidenote {
  float: right;
  position: relative;
  margin-right: -18vw;
  width: 40%;
  max-width: 200px;
}
body {
  counter-reset: sidenote-counter;
}
.sidenote-number {
  counter-increment: sidenote-counter;
}
.sidenote::before {
  content: "# ";
  position: relative;
  font-size: 0.9em;
  font-weight: 700;
  color: red;
}
.sidenote-number::after {
  content: "#";
  vertical-align: super;
  font-size: 0.8em;
  font-weight: 700;
  color: #409dff;
}
.sidenote-number:hover .sidenote {
  background-color: var(--sidenote-bg);
}

光有 CSS 还不够,我们上面定义的这些特殊的 HTML 元素,都得创建才行,在 layouts/shortcodes/sidenote.html 中写入以下内容

<span class="sidenote-number"><small class="sidenote">{{ .Inner | markdownify }}</small></span>

.Inner 就代表是输入的内容,而 | markdownify 是为了支持 markdown 渲染,比如超链接等语法

图片点击放大

Black Holes: Monsters in Space

Black Holes: Monsters in Space

当图片细节很多或图片很大时,放在博客上就难免会进行大比例缩放,此时读者若是不能放大查看该图片,想必会十分苦恼,故而图片点击放大的功能也是必不可少的,具体是通过引入 fancybox 来实现:

在 layouts/shortcodes/figure.html 中填入以下内容即可

figure.html
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/[email protected]/dist/jquery.fancybox.min.css" />
<script src="https://cdn.jsdelivr.net/gh/fancyapps/[email protected]/dist/jquery.fancybox.min.js"></script>

<a data-fancybox="gallery" href="{{ .Get "src" }}">
<figure{{ if or (.Get "class") (eq (.Get "align") "center") }} class="
           {{- if eq (.Get "align") "center" }}align-center {{ end }}
           {{- with .Get "class" }}{{ . }}{{- end }}"
{{- end -}}>
    {{- if .Get "link" -}}
        <a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{ . }}"{{ end }}{{ with .Get "rel" }} rel="{{ . }}"{{ end }}>
    {{- end }}
    <img loading="lazy" src="{{ .Get "src" }}{{- if eq (.Get "align") "center" }}#center{{- end }}"
         {{- if or (.Get "alt") (.Get "caption") }}
         alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" | markdownify| plainify }}{{ end }}"
         {{- end -}}
         {{- with .Get "width" }} width="{{ . }}"{{ end -}}
         {{- with .Get "height" }} height="{{ . }}"{{ end -}}
    /> <!-- Closing img tag -->
    {{- if .Get "link" }}</a>{{ end -}}
    {{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
        <figcaption>
            {{ with (.Get "title") -}}
                {{ . }}
            {{- end -}}
            {{- if or (.Get "caption") (.Get "attr") -}}<p>
                {{- .Get "caption" | markdownify -}}
                {{- with .Get "attrlink" }}
                    <a href="{{ . }}">
                {{- end -}}
                {{- .Get "attr" | markdownify -}}
                {{- if .Get "attrlink" }}</a>{{ end }}</p>
            {{- end }}
        </figcaption>
    {{- end }}
</figure>
</a>

当然上面还不止是增加了图片点击放大的功能,还加了 align,caption 等功能

盘古之白

个人认为,中文和英文以及数字之间有空格会更加便于阅读,这个空格也被称为「盘古之白」,像是劈开了这几者之间的混沌, 实现起来也十分简便:

在 layouts/partials/extend_footer.html 中加入以下内容:

盘古之白配置
{{- `$highlight := resources.Get "js/pangu.min.js" }}$`
<script>
    (function(u, c) {
      var d = document, t = 'script', o = d.createElement(t),
          s = d.getElementsByTagName(t)[0];
      o.src = u;
      if (c) { o.addEventListener('load', function(e) { c(e); }); }
      s.parentNode.insertBefore(o, s);
    })('{{ `$highlight.RelPermalink }}', function() {$`
      pangu.spacingPage();
    });
</script>

我这里是将 pangu.min.js 下载到了网站本地,具体是在 assets/js/pangu.min.js,当网站加载时,盘古之白会自动进行渲染

代码折叠

示例代码
print('Acc: 100%')

对于代码比较多的 blog,比如这篇,很多代码较长会影响阅读,占用很多篇幅,如果可以折叠,需要的时候点击展开就会很方便,折叠功能实现起来也比较方便,在 layouts/shortcodes/collapse.html 中加入以下内容:

{{ if .Get "summary" }}
{{ else }}
{{ warnf "missing value for param 'summary': %s" .Position }}
{{ end }}
<p><details {{ if (eq (.Get "openByDefault") true) }} open=true {{ end }}>
  <summary markdown="span">{{ .Get "summary" | markdownify }}</summary>
  {{ .Inner | markdownify }}
</details></p>

版权声明

也许你也需要修改文章末尾的版权说明,那么就在 layouts/partials/post_copyright.html 中加入自己的版权声明即可

文章分类

有时候我们想要发表截然不同类型的文章,比如我主要会发深度学习以及 AI 相关的,但我也会写「折腾」相关的,就需要有不同的分类

先在 config.yaml 中加入以下内容:

params:
  taxonomies:
    category: categories
    tag: tags

然后在写文章的时候,可以编辑文章的元信息来进行分类,同时还可以不在主页显示

---
title: 新的主题
date: 2022-06-19 11:10:00 +0800
categories: [折腾]
hiddenInHomeList: true
...
---

但是不在主页显示后读者就不容易找到,此时我们在 config.yaml 中额外加个 menu 即可:

menu:
  main:
    ...
    - identifier: categories
      name: 折腾
      url: /categories/折腾
      weight: 20

Shortcodes 大赏

这里分享一些我比较常用的shortcode,也欢迎评论区分享你觉得有趣的

旋转的友链

Aaron Swartz
用以缅怀自由斗士 Aaron

当鼠标悬浮至友链所对应的头像时,头像便会开始进行旋转,这个还挺有趣的,首先在 assets/css/extended/friends.css 中加入以下内容: 借鉴了 sulvblog

旋转友链的 CSS 设置
.friendurl {
  text-decoration: none !important;
  color: black;
  box-shadow: none !important;
}

.myfriend {
  width: 56px !important;
  height: 56px !important;
  border-radius: 50% !important;
  padding: 2px;
  margin-top: 20px !important;
  margin-left: 14px !important;
  background-color: #fff;
}

.frienddiv {
  overflow: auto;
  height: 100px;
  width: 49%;
  display: inline-block !important;
  border-radius: 5px;
  background: none;
  -webkit-transition: all ease-out 0.3s;
  -moz-transition: all ease-out 0.3s;
  -o-transition: all ease-out 0.3s;
  transition: all ease-out 0.3s;
}

.dark .frienddiv:hover {
  background: var(--code-bg);
}

.frienddiv:hover {
  background: var(--theme);
  transition: transform 1s;
  webkit-transform: scale(1.1);
  -moz-transform: scale(1.2);
  -ms-transform: scale(1.2);
  -o-transform: scale(1.2);
  transform: scale(1.1);
}

.frienddiv:hover .frienddivleft img {
  transition: 0.9s !important;
  -webkit-transition: 0.9s !important;
  -moz-transition: 0.9s !important;
  -o-transition: 0.9s !important;
  -ms-transition: 0.9s !important;
  transform: rotate(360deg) !important;
  -webkit-transform: rotate(360deg) !important;
  -moz-transform: rotate(360deg) !important;
  -o-transform: rotate(360deg) !important;
  -ms-transform: rotate(360deg) !important;
}

.frienddivleft {
  width: 92px;
  float: left;
  margin-right: -5px;
}

.frienddivright {
  margin-top: 18px;
  margin-right: 18px;
}

.friendname {
  text-overflow: ellipsis;
  font-size: 100%;
  margin-bottom: 5px;
  color: var(--primary);
}

.friendinfo {
  text-overflow: ellipsis;
  font-size: 70%;
  color: var(--primary);
}

@media screen and (max-width: 600px) {
  .friendinfo {
    display: none;
  }
  .frienddivleft {
    width: 84px;
    margin: auto;
  }
  .frienddivright {
    height: 100%;
    margin: auto;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .friendname {
    font-size: 18px;
  }
}

接着在 layouts/shortcodes/friend.html 中加入以下内容:

friend.html 内容
{{- if .IsNamedParams -}}
<a target="_blank" href={{ .Get "url" }} title={{ .Get "name" }} class="friendurl">
  <div class="frienddiv">
    <div class="frienddivleft">
      <img class="myfriend" src={{ .Get "logo" }} />
    </div>
    <div class="frienddivright">
      <div class="friendname">{{- .Get "name" -}}</div>
      <div class="friendinfo">{{- .Get "word" -}}</div>
    </div>
  </div>
</a>
{{- end }}

Blockquote

Basically, I’m not interested in doing research and I never have been… I’m interested in understanding, which is quite a different thing. And often to understand something you have to work it out yourself because no one else has done it. — David Blackwell

这个主题原来的 blockquote 较为丑,在 layouts/shortcodes/quote.html 加入以下内容 借鉴了 Guan Qirui

Blockquote html 设置
<blockquote class="quote{{ range .Params }} {{ . }}{{ end }}">
    {{- `$content := .Inner | markdownify -}}$`
    {{- if not (strings.HasPrefix `$content "<p>") }}$`
        {{ printf `<p>%s</p>` `$content | safeHTML }}$`
    {{- else }}
        {{- `$content }}$`
    {{- end -}}
</blockquote>

Github 小卡片

Github 仓库小卡片对我来说还是比较重要的,因为我一般代码都会进行开源,如果可以用一种卡片的方式提醒读者开源代码所在处,就省了读者去查找的功夫了,首先在 assets/css/extended/github.css 中填入以下内容:

Github 卡片相关 CSS 设置
.github {
  border: 0px solid;
  border-radius: 5px;
  width: 95%;
  margin-bottom: 1em;
  margin-top: 1em;
  padding: 1em;
  background-color: var(--code-bg);
  .github_bar {
    margin-top: -0.6em;
    margin-left: 0;
  }
  .github_name {
    font-weight: bold;
    text-decoration: none;
    font-size: 24px;
    position: relative;
    top: -0.6em;
    left: 0.3em;
  }
  .github_description {
    margin-top: -0.3em;
    margin-bottom: 1em;
    color: var(--color-contrast-high);
    text-align: justify;
    font-size: 90%;
    width: 95%;
    transition: all 0.5s;
  }
  .github_language {
    margin-top: -0.6em;
  }
  .github_language_name {
    color: var(--color-contrast-high);
    font-size: 90%;
    margin-left: 0.5em;
    transition: all 0.5s;
  }
}

接着,在 layouts/shortcodes/github.html 中加入以下内容:

github.html 内容
<div class="github">
    <div class="github_bar">
        {{ replace `$.Site.Data.SVG.repository "icon" "icon github-icon" | safeHTML }}$`
        <a class="github_name" href={{ .Get "link" }} target="_blank">{{ .Get "name" }}</a>
    </div>
    <div class="github_description">{{ .Get "description" }}</div>
    <div class="github_language">
        {{ .Get "language" }}
    </div>
</div>

最后在 data 中添加 SVG.toml 并加入以下内容

repository = '<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50"><path d="M17.791,46.836C18.502,46.53,19,45.823,19,45v-5.4c0-0.197,0.016-0.402,0.041-0.61C19.027,38.994,19.014,38.997,19,39 c0,0-3,0-3.6,0c-1.5,0-2.8-0.6-3.4-1.8c-0.7-1.3-1-3.5-2.8-4.7C8.9,32.3,9.1,32,9.7,32c0.6,0.1,1.9,0.9,2.7,2c0.9,1.1,1.8,2,3.4,2 c2.487,0,3.82-0.125,4.622-0.555C21.356,34.056,22.649,33,24,33v-0.025c-5.668-0.182-9.289-2.066-10.975-4.975 c-3.665,0.042-6.856,0.405-8.677,0.707c-0.058-0.327-0.108-0.656-0.151-0.987c1.797-0.296,4.843-0.647,8.345-0.714 c-0.112-0.276-0.209-0.559-0.291-0.849c-3.511-0.178-6.541-0.039-8.187,0.097c-0.02-0.332-0.047-0.663-0.051-0.999 c1.649-0.135,4.597-0.27,8.018-0.111c-0.079-0.5-0.13-1.011-0.13-1.543c0-1.7,0.6-3.5,1.7-5c-0.5-1.7-1.2-5.3,0.2-6.6 c2.7,0,4.6,1.3,5.5,2.1C21,13.4,22.9,13,25,13s4,0.4,5.6,1.1c0.9-0.8,2.8-2.1,5.5-2.1c1.5,1.4,0.7,5,0.2,6.6c1.1,1.5,1.7,3.2,1.6,5 c0,0.484-0.045,0.951-0.11,1.409c3.499-0.172,6.527-0.034,8.204,0.102c-0.002,0.337-0.033,0.666-0.051,0.999 c-1.671-0.138-4.775-0.28-8.359-0.089c-0.089,0.336-0.197,0.663-0.325,0.98c3.546,0.046,6.665,0.389,8.548,0.689 c-0.043,0.332-0.093,0.661-0.151,0.987c-1.912-0.306-5.171-0.664-8.879-0.682C35.112,30.873,31.557,32.75,26,32.969V33 c2.6,0,5,3.9,5,6.6V45c0,0.823,0.498,1.53,1.209,1.836C41.37,43.804,48,35.164,48,25C48,12.318,37.683,2,25,2S2,12.318,2,25 C2,35.164,8.63,43.804,17.791,46.836z"></path></svg>'

各种 notice

一生疏狂尽余欢,半剖肝胆入剑寒。 剑至高危如蜀道,生逢穷途行路难。

一生疏狂尽余欢,半剖肝胆入剑寒。 剑至高危如蜀道,生逢穷途行路难。

一生疏狂尽余欢,半剖肝胆入剑寒。 剑至高危如蜀道,生逢穷途行路难。

一生疏狂尽余欢,半剖肝胆入剑寒。 剑至高危如蜀道,生逢穷途行路难。

在 layouts/shortcodes 中创建 notice.html,然后复制以下内容: 借鉴了 Hugo-notice

notice.html 内容
{{- `$noticeType := .Get 0 -}}$`

{{- `$raw := (markdownify .Inner | chomp) -}}$`

{{- `$block := findRE "(?is)^<(?:address|article|aside|blockquote|canvas|dd|div|dl|dt|fieldset|figcaption|figure|footer|form|h(?:1|2|3|4|5|6)|header|hgroup|hr|li|main|nav|noscript|ol|output|p|pre|section|table|tfoot|ul|video)\\b" $`raw 1 -}}

{{ `$icon := (replace (index site.Data.SVG $`noticeType) "icon" "icon notice-icon") }}
<div class="notice {{ `$noticeType }}" {{ if len .Params | eq 2 }} id="{{ .Get 1 }}" {{ end }}>$`
    <div class="notice-title">{{ `$icon | safeHTML }}</div>$`
    {{- if or `$block (not $`raw) }}{{ `$raw }}{{ else }}<p>{{ $`raw }}</p>{{ end -}}
</div>

接着在 assets/extended 中创建 notice.css 并填入以下内容:

notice.css 内容
.notice {
  display: flex;
  align-items: center;
  position: relative;
  padding: 0.6em;
  margin-bottom: 1em;
  border-radius: 4px;
  p:last-child {
    margin-bottom: 0;
  }
  .notice-title {
    margin-right: 0.5em;
    margin-top: 0.5em;
    .notice-icon {
      width: 1.2em;
      height: 1.2em;
    }
  }
  &.notice-warning {
    background: hsla(0, 65%, 65%, 0.15);
    .notice-title {
      color: hsl(0, 65%, 65%);
    }
  }
  &.notice-info {
    background: hsla(30, 80%, 70%, 0.15);
    .notice-title {
      color: hsl(30, 80%, 70%);
    }
  }
  &.notice-note {
    background: hsla(200, 65%, 65%, 0.15);
    .notice-title {
      color: hsl(200, 65%, 65%);
    }
  }
  &.notice-tip {
    background: hsla(140, 65%, 65%, 0.15);
    .notice-title {
      color: hsl(140, 65%, 65%);
    }
  }
}

最后在 data/SVG.toml 中加入以下内容:

notice-warning = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 576 512"><path d="M570 440c18 32-5 72-42 72H48c-37 0-60-40-42-72L246 24c19-32 65-32 84 0l240 416zm-282-86a46 46 0 100 92 46 46 0 000-92zm-44-165l8 136c0 6 5 11 12 11h48c7 0 12-5 12-11l8-136c0-7-5-13-12-13h-64c-7 0-12 6-12 13z"/></svg>'
notice-info = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512"><path d="M256 8a248 248 0 100 496 248 248 0 000-496zm0 110a42 42 0 110 84 42 42 0 010-84zm56 254c0 7-5 12-12 12h-88c-7 0-12-5-12-12v-24c0-7 5-12 12-12h12v-64h-12c-7 0-12-5-12-12v-24c0-7 5-12 12-12h64c7 0 12 5 12 12v100h12c7 0 12 5 12 12v24z"/></svg>'
notice-note = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512"><path d="M504 256a248 248 0 11-496 0 248 248 0 01496 0zm-248 50a46 46 0 100 92 46 46 0 000-92zm-44-165l8 136c0 6 5 11 12 11h48c7 0 12-5 12-11l8-136c0-7-5-13-12-13h-64c-7 0-12 6-12 13z"/></svg>'
notice-tip = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512"><path d="M504 256a248 248 0 11-496 0 248 248 0 01496 0zM227 387l184-184c7-6 7-16 0-22l-22-23c-7-6-17-6-23 0L216 308l-70-70c-6-6-16-6-23 0l-22 23c-7 6-7 16 0 22l104 104c6 7 16 7 22 0z"/></svg>'