博客折腾笔记

之前用过wordpress,但在16g的傲腾上跑wordpress果然还是太勉强了,所以最后还是选了hugo.
不幸的是hugo本身是不支持mermaid和katex的,为了让各种公式和图表正常显示又是一阵折腾.
幸运的是hugo作为静态站点能直接用webhook+脚本完成自动更新(之前的gitea没白搭),但众所周知跟DevOps沾点边的就没有轻松活……所以也没幸运到哪去.
总之以下是关于大致过程的记录.

思路

Gitea提交时触发webhook,使本地的deploy.sh完成自动更新

hugo

# hugo.toml
baseURL = 'https://hugo.starcells.ltd/'
languageCode = 'zh-cn'
title = 'Starcells.ltd'
theme = 'PaperMod'

[author]
    name = "StarCells"

[params]
    defaultTheme = "auto"
    showCodeCopyButtons = true
    math = true #Katex需要开这个
    author = "StarCells"

为了以防万一还是在这里也放一份吧,hugo本身的配置文件,这个倒算轻松

<!-- archetypes/default.md -->

+++
date = '{{ .Date }}'
draft = true
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
+++

这样hugo new的时候就会自动填充了

mermaid

<!-- layouts/_markup/render-codeblock-mermaid.html -->
<div class="mermaid">{{- .Inner | safeHTML -}}</div>
<!-- layouts/partials/extend_head.html -->
{{ if or .Params.math .Site.Params.math }}
{{ partial "math.html" . }}
{{ end }}
<script src="{{ "js/mermaid.min.js" | relURL }}"></script>
<script>
    document.addEventListener("DOMContentLoaded", function() {
        mermaid.initialize({
            startOnLoad: true,
            theme: document.body.classList.contains('dark') ? 'dark' : 'default'
        });

        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.attributeName === 'class') {
                    const isDark = document.body.classList.contains('dark');
                    mermaid.initialize({ theme: isDark ? 'dark' : 'default' });
                    location.reload();
                }
            });
        });
        observer.observe(document.body, { attributes: true });
    });
</script>

这俩负责加入mermaid支持,在static/js下面拉取mermaid.min.js就可以了

katex

<!-- layouts/partials/math.html -->
<link
    rel="stylesheet"
    href="{{ "css/katex.min.css" | relURL }}"
/>

<script defer src="{{ "js/katex/katex.min.js" | relURL }}"></script>

<script defer src="{{ "js/katex/auto-render.min.js" | relURL }}"
    onload="
    window.addEventListener('DOMContentLoaded', function() {
        renderMathInElement(document.body, {
            delimiters: [
                {left: '$$', right: '$$', display: true},
                {left: '$', right: '$', display: false},
                {left: '\\$$', right: '\\\\$$', display: false},
                {left: '\\$$', right: '\\\\$$', display: true}
            ]
        });
    });
"></script>

这个提供Katex支持,需要在static/katex下拉取katex.min.jsauto-render.min.js,在static/css下拉取katex.min.css

webhook

#!/bin/sh

# deploy.sh

BLOGDIR=/var/www/myblog

cd $BLOGDIR

/usr/bin/git clean -fdx

/usr/bin/git fetch --all
/usr/bin/git reset --hard origin/master
/usr/bin/git pull
/usr/bin/git submodule update --init --recursive

find content -name "*.md" -exec sed -i 's/\\\{/\\\\\{/g' {} +
find content -name "*.md" -exec sed -i 's/\\\}/\\\\\}/g' {} +

/usr/bin/hugo --gc --minify

chown -R caddy:caddy public/

稍微解释一下那两行find吧,不知道为什么在hugo和ghostwriter的pandoc Github-flavored Markdown里,单个\无法转义{},大括号会直接消失,在公式里表示集合的时候简直致命
只有先对\本身进行转义才能使{}正常显示,因此在生成时需要对\\{\\}进行替换

- id: redeploy-blog
  execute-command: /var/www/myblog/deploy.sh
  command-working-directory: /var/www/myblog
  response-message: "Deploying... check server logs for details."

  include-command-output-in-response: true

  trigger-rule:
    and:
      - match:
          type: value
          value: refs/heads/master
          parameter:
            source: payload
            name: ref
      - match:
          type: payload-hmac-sha256
          secret: "这里是密钥"
          parameter:
            source: header
            name: X-Gitea-Signature

看着轻松,一个sh一个conf就全搞定了,实际上鬼知道调试花了多久

caddy

hugo.starcells.ltd {
    root * /var/www/myblog/public

    # 开启静态文件服务
    file_server

    # 开启压缩
    encode zstd gzip

    # 安全响应头
    header {
        # 允许跨域
        Access-Control-Allow-Origin *
        # 防点击劫持
        X-Frame-Options "SAMEORIGIN"
    }

    # 错误页面处理
        handle_errors {
            rewrite * /{err.status_code}.html
            file_server
        }
}

最后是Caddyfile.