便当的梅开五度

从 Hexo 到 Hugo, 以及一些想说的话

如果文章中的图片加载不出来, 请您考虑使用代理软件.

此文章使用 CC-BY-NC 协议.


目录


前言

如果您是本站的老读者, 一定见证过这样一件奇异的事:

网站的框架, 域名和主题明明都是好好的, 却还是变来变去!

没错, 这也就是本站站名的由来. 到了今天, 已经是第五次大变革.

我好像就是如此一个人. 无论是手机系统, 电脑系统, 亦或是博客系统, 总是在稳定下来后想要换一换.


那么, 先回忆一下

第一次写博客, 用的是 WordPress. 网站至今还在: https://thdbd666666.wordpress.com/

在那之前, 我也写过网站. 用那个什么 所见即所得 的写 html 的软件一行一行敲的. 那会儿找到很好看的 css 和 js 都会写一个新网页扔里面. 不过严格来说, 并不能算 网站, 因为我只是在浏览器里预览那些 html, 跳转也是如此.

2021年7月10日, 已经过去这么久了…

当时就是觉得有一个自己的网站很酷, 于是有什么东西都想写下来.

渐渐地, 因为会员限制, 主题限制, 以及 “不酷” 的广告横幅, 我想换个方式了.

用 WordPress 时, 我还不知道什么叫 markdown, 也不知道所谓 静态博客动态博客.

我的关键词是 免费建站, 博客. 这样一番搜索下来, 我才知道了上面这三个东西.

以及我的梅开二度: GitBook: https://thdbd.gitbook.io/thdbd/.

GitBook 至今也是很好看啊, 感觉还是能派上一些用场的.

正如那时所言, 学会 markdown 后, 加以 GitBook 真的很方便.

不过后来知道了 Hexo 的存在后, 我又创建了第三个博客: https://thdbd.github.io/.

这也是一个 GitHub Pages, 不过用的是另一个账号.

梅开三度, 我在此期间学会了不少东西: 学会 git, 学会 python, 学会写 tg bot 等等.

这个时期也产出了大量的博客文章.

直到那次换系统没备份, 丢了许多文章, 自那以后我才意识到备份的重要性.

于是, 卷土重来, 梅开四度. 也就是本站的域名.

梅开四度是时间存在最长的一 . 我的博客阅读量上来了, 甚至开始有了评论.

这些都让我欣喜若狂.

不过我还是想换. 我想换主题, 想换个简洁一些的, 移动端 UI 美观的, 以及 读感 更好的.

于是我想到了 Hugo, 于是我找到了 Paper 主题.

其实在文章数量不多的情况下, Hugo 跟 Hexo 的生成速度相差不大, 而且我目前用的这个主题的功能也不如之前的多.

可我还是换了.

我想, 可能是因为在这些换来换去中, 我见过了太多的错, 踩了太多的坑, 即使遇到新的问题, 我也不怕了.

我花了3个小时来设置我的新的网站.


转到 Hugo 的一些操作

Gemini 为我总结了一些差别:

特性 Hexo Hugo
安装依赖 需要 Node.js, npm 单一二进制文件(解压即用)
文章目录 source/_posts content/posts
静态资源 source/images static/images
配置文件 _config.yml hugo.toml(也支持 yaml/json)
渲染引擎 Nunjucks / Swig / EJS Go Templates

Hugo 存在于 openSUSE 的包管理器中, 且没什么依赖真是一件好事.

原先都是为了 Hexo 这碟醋装了 nodejs, npm 一系列依赖, 如今储存空间又大了一些.

建站

hugo new site 博客
cd 博客
git init
git submodule add https://github.com/nanxiaobei/hugo-paper themes/paper

四条命令完成建站.

同时给大家分享一下我的配置文件:

baseURL = 'https://wzk0.github.io/'
languageCode = 'zh-CN'
title = '便当的梅开五度'
theme = "paper"

[taxonomies]
  category = 'categories'
  tag = 'tags'
  series = 'series'

[markup]
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true
      
[params]
  # color style
  color = 'linen'                           # linen, wheat, gray, light

  # header social icons
  twitter = 'thd_bd'               # twitter.com/YOUR_TWITTER_ID
  github = 'wzk0'                 # github.com/YOUR_GITHUB_ID
  rss = true                                # show rss icon

  # home page profile
  # avatar = 'thdbd@qq.com'                 # gravatar email or image url
  # name = '听话的便当'
  # bio = 'YOUR_BIO'

  # misc
  disableHLJS = false                        # disable highlight.js
  disablePostNavigation = false              # disable post navigation
  monoDarkIcon = true                       # show monochrome dark mode icon
  gravatarCdn = 'GRAVATAR_CDN_LINK'         # e.g. 'https://cdn.v2ex.com/gravatar/'
  math = true                               # enable KaTeX math typesetting globally
  localKatex = false                        # use local KaTeX js/css instead of CDN
  favicon = "favicon.png"                   # customize the default favicon
  appleTouchIcon = "apple-touch-icon.png"   # customize the default Apple touch icon

  # RTL supprot
  direction = "ltr"                         # RTL support for Right-to-left languages

  # giscus
[params.giscus]
  repo = 'wzk0/my_giscus'                 # see https://giscus.app for more details
  repoId = 'xxxxx'
  category = 'Announcements'
  categoryId = 'xxxxx'
  mapping = 'pathname'
  theme = 'light'
  lang = 'zh-CN'

[[menu.main]]
    identifier = "tags"
    name = "标签"
    url = "/tags/"
    weight = 1

[[menu.main]]
    identifier = "categories"
    name = "分类"
    url = "/categories/"
    weight = 2

[[menu.main]]
    identifier = "about"
    name = "关于"
    url = "/about/"
    weight = 3

配置

对于 标签, 分类关于 三个页面, 使用以下指令新建:

hugo new content about.md
hugo new content tags/_index.md
hugo new content categories/_index.md

对于 标签分类 页面, 个人做了一些更改:

👇 博客/themes/paper/layouts/_default/list.html

{{- define "main" -}}

{{- if not .IsHome -}}
{{- if or (eq .Type "tags") (eq .Type "categories") -}}
<h1 class="mb-14">
  # {{ .Title }}
</h1>
{{- end -}}
{{- end -}}

{{- $pages := .Pages -}}
{{- if .IsHome -}}
{{- $pages = where site.RegularPages "Type" "in" (site.Params.mainSections | default (slice "posts")) -}}
{{- end -}}

{{- $paginator := .Paginate $pages -}}

{{- range $index, $page := $paginator.Pages -}}

{{- if and $.IsHome (eq $paginator.PageNumber 1) (eq $index 0) -}}
{{- $avatar_url := $.Scratch.Get "avatar_url" -}}
{{- if or $avatar_url site.Params.name -}}
<div class="mb-12 flex items-center">
  {{- if $avatar_url -}}
  <div
    class="h-24 w-24 shrink-0 rounded-full border-[0.5px] border-black/10 bg-white/50 p-3 ltr:mr-5 ltr:-ml-1 rtl:-mr-1 rtl:ml-5 dark:bg-white/90!">
    <img class="not-prose my-0 h-full w-full rounded-full bg-black/5! hover:animate-spin dark:bg-black/80!"
      src="{{- $avatar_url -}}" alt="{{- site.Params.name | default site.Title -}}" />
  </div>
  {{- end -}}
  {{- if site.Params.name -}}
  <div>
    <div class="mt-3 mb-1 text-2xl font-medium text-black dark:text-white">
      {{- site.Params.name -}}
    </div>
    <div class="break-words">
      {{- site.Params.bio | default (print `A personal blog by ` site.Params.name) -}}
    </div>
  </div>
  {{- end -}}
</div>
{{- end -}}
{{- end -}}

<section class="relative my-10 first-of-type:mt-0 last-of-type:mb-0">
  {{- if gt .Weight 0 -}}
  <span class="mb-1 inline-block text-xs tracking-wider text-orange-500">精选置顶</span>
  {{- end -}}
  <h2 class="my-0!">{{- .Title -}}</h2>
  <time class="text-xs antialiased opacity-60">
    Created @{{- .Date | time.Format ":date_medium" -}}
  </time>
  <a class="absolute inset-0 text-[0px]" href="{{- .Permalink -}}">{{- .Title -}}</a>
</section>

{{- end -}}

{{- if gt $paginator.TotalPages 1 -}}
<nav class="mt-14 flex">
  {{- if $paginator.HasPrev -}}
  <a class="btn not-prose" href="{{- $paginator.Prev.URL -}}">← 上一页</a>
  {{- end -}}
  {{- if $paginator.HasNext -}}
  <a class="btn not-prose ml-auto" href="{{- $paginator.Next.URL -}}">下一页 →</a>
  {{- end -}}
</nav>
{{- end -}}

{{- end -}}

写法

Hugo 支持 Rich Content, 同时我觉得 Paper 的 code 样式有点丑, 而 标签作为 code 似乎更适合.

遂写一个 fish 函数处理:

function md2kbd
    python3 -c "
import re, os
pattern = re.compile(r'(?s)```.*?```|`([^`\\n]+)`')
def replace(m):
    if m.group(0).startswith('```'): return m.group(0)
    return f'<kbd>{m.group(1)}</kbd>'
for f in [f for f in os.listdir('.') if f.endswith('.md')]:
    with open(f, 'r+') as file:
        content = file.read()
        file.seek(0)
        file.write(pattern.sub(replace, content))
        file.truncate()
    print(f'Done: {f}')
"
end

执行后会自动把所有 ` 变为 < kbd >.


关于旧文章的处理办法

由于 Hugo front matterdate, tagscategories 的命名规则与 Hexo 不同.

手动迁移有些麻烦. 同时原先的文章中有些包含 paper 不支持的 html.

于是我打算将旧博客放在 /4 下面. 因此编写一个 fish 函数来手动处理 hugo build 的产物.

function bup
    cd ~/博客
    rm -rf public && hugo build
    cd wzk0.github.io
    find . -maxdepth 1 -not -path . -not -name "4" -not -name ".git" -exec rm -rf {} +
    mv ../public/* .
    git add * . && git commit -m "更新时间: $(date +%Y-%m-%d)" && git push -u origin main
end

关于 AI

由于 paper 不支持文章侧边目录, 所以以后的每一篇文章, 我都会在开头加上由 AI 生成的目录.

我的提示词如下:

你是一个 hugo 目录总结助手, 我总是会发给你我的 markdown 格式的文本, 你需要做的事就是:
1. 根据标题等级总结出文章的目录. 如果此篇文章内容分级不深, 仅用了二级标题##, 且内容与列举多项有关, 或我主动强调, 你都要发给我表格形式的markdown代码.
2. 当分级多且深时, 发给我- 这样的目录, 也是 markdown 代码.
3. 所有标点符号应该为半角, 英文与中文之间必须有空格, 标点符号后必须有空格.
4. 目录中的标题设为点击后跳转到指定位置.

最后

感谢一直以来读者朋友们的支持. 希望换到 Hugo 以后, 我的博客热情能再高一些, 同时也能给大家带来更多的帮助.