Hugo Stack主题配置与使用

修改文件名

遍历当前目录下的所有 .md 文件,为每个文件创建一个同名文件夹,并将文件移动进去重命名为 index.md

您可以将以下代码保存为 batch_convert.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash

# 遍历当前目录下所有的 .md 文件
for file in *.md; do
    # 检查文件是否存在(防止没有 md 文件时报错)
    [ -e "$file" ] || continue

    # 1. 获取文件名(不带扩展名),例如将 "A.md" 转换为 "A"
    dir_name="${file%.*}"

    # 排除 index.md 自身(防止递归处理或错误创建 index 文件夹)
    if [ "$dir_name" == "index" ]; then
        continue
    fi

    # 2. 创建同名文件夹(如果文件夹已存在也不会报错)
    mkdir -p "$dir_name"

    # 3. 将文件复制到文件夹中并重命名为 index.md
    # 这步操作等同于:先复制进去,再改名
    mv "$file" "$dir_name/index.md"

    echo "已处理: $file -> $dir_name/index.md"
done

又换主题了,这回使用的是hugo-theme-stack,无意发现这款主题,正合我意,够简单,最重要的是支持本地搜索,再不用弄哪个Alogia了。

下载主题&更新主题

  1. 下载主题
1
2
git init
git submodule add https://github.com/iwyang/hugo-theme-stack/ themes/hugo-theme-stack
  1. 更新主题
1
git submodule update --remote

查看主题版本号

1
2
3
4
git show 查看当前版本
----------------------------------------------------------------
git tag 列出所有版本号
git checkout +某版本号 (你当前文件夹下的源码会变成这个版本号的源码)

config.yaml配置文件

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
baseurl: /
languageCode: zh-CN
theme: hugo-theme-stack
paginate: 10
title: Bore's Notes

# Change it to your Disqus shortname before using
# disqusShortname: 

# GA Tracking ID
googleAnalytics:

# Theme i18n support
# Available values: en, fr, id, ja, ko, pt-br, zh-cn, zh-tw, es, de, nl, it, th, el, uk
DefaultContentLanguage: zh-cn

# Set hasCJKLanguage to true if DefaultContentLanguage is in [zh-cn ja ko]
# This will make .Summary and .WordCount behave correctly for CJK languages.
hasCJKLanguage: true

permalinks:
    post: /archives/:slug/
    page: /:slug/
    
# whether to use emoji code
enableEmoji: true

params:
    mainSections:
        - post
    featuredImageField: image
    rssFullContent: true
    favicon: /img/favicon.png

    footer:
        since: 2020
        customText:

    dateFormat:
        published: 2006-01-02
        lastUpdated: 2006-01-02

    sidebar:
        emoji: 🍥
        subtitle: 博观而约取,厚积而薄发
        avatar:
            enabled: false
            local: true
            src: img/avatar.jpg

    article:
        math: false
        toc: true
        readingTime: false 
        license:
            enabled: false
            default: Licensed under CC BY-NC-SA 4.0
        edit:
            enabled: true

    comments:
        enabled: true
        provider: waline
        
        disqusjs:
            shortname:
            apiUrl:
            apiKey:
            admin:
            adminLabel:

        utterances:
            repo: 
            issueTerm: title
            label: utterances
            theme: dark-orange

        remark42:
            host:
            site:
            locale:

        vssue:
            platform:
            owner:
            repo:
            clientId:
            clientSecret:
            autoCreateIssue: false

        # Waline client configuration see: https://waline.js.org/en/reference/client.html
        waline:
            serverURL: https://your-domain.vercel.app
            lang: zh-CN
            visitor: false
            avatar: mp
            emoji:
                - https://cdn.jsdelivr.net/gh/walinejs/emojis/weibo
            requiredMeta:
                - nick
                - mail
            placeholder: 欢迎评论
            locale:
                admin: 博主
   
        twikoo:
            envId: https://twikoo-lake.vercel.app
            region:
            path:
            lang:
            
        giscus:
            repo:
            repoID:
            category:
            categoryID:
            mapping:
            lightTheme:
            darkTheme:
            reactionsEnabled: 1
            emitMetadata: 0
            
        gitalk:
            owner: 
            admin:  
            repo: 
            clientID: 
            clientSecret: 
            
        cusdis:
            host: 
            id: 

    widgets:
        enabled:
            - search
            - categories
            - tag-cloud
            - archives
           
        archives:
            limit: 10000

        tagCloud:
            limit: 10000
            
        categoriesCloud:
            limit: 10000

    opengraph:
        twitter:
            # Your Twitter username
            site:

            # Available values: summary, summary_large_image
            card: summary_large_image

    defaultImage:
        opengraph:
            enabled: false
            local: false
            src:

    colorScheme:
        # Display toggle
        toggle: true

        # Available values: auto, light, dark
        default: auto

    imageProcessing:
        cover:
            enabled: true
        content:
            enabled: true

### Custom menu
### See https://docs.stack.jimmycai.com/configuration/custom-menu.html
### To remove about, archive and search page menu item, remove `menu` field from their FrontMatter
menu:
    main:
        - identifier: home
          name: 首页
          url: /
          weight: -100
          pre: home
          params:
              ### For demonstration purpose, the home link will be open in a new tab
              newTab: false
              icon: home
    # social:
        # - identifier: github
          # name: GitHub
          # url: https://github.com/iwyang
          # params:
            # icon: brand-github
            
        # - identifier: twitter
          # name: Twitter
          # url: https://twitter.com
          # params:
            # icon: brand-twitter

related:
    includeNewer: true
    threshold: 60
    toLower: false
    indices:
        - name: tags
          weight: 100

        - name: categories
          weight: 200

markup:
    goldmark:
        renderer:
            ## Set to true if you have HTML content inside Markdown
            unsafe: true
    tableOfContents:
        endLevel: 4
        ordered: true
        startLevel: 2
    highlight:
        noClasses: false

archetypes默认模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
title: "{{ replace .TranslationBaseName "-" " " | title }}"
slug: ""
description: ""
date: {{ .Date }}
lastmod: {{ .Date }}
draft: false
toc: true
weight: false
image: ""
categories: [""]
tags: [""]

显示右侧工具栏分类目录

参考 https://github.com/CaiJimmy/hugo-theme-stack/issues/169

最新版主题已默认开启分类目录工具栏

  1. Create categories.html in layouts/partials/widget
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<section class="widget tagCloud">
  <div class="widget-icon">
      {{ partial "helper/icon" "categories" }}
  </div>
  <h2 class="widget-title section-title">{{ T "widget.categoriesCloud.title" }}</h2>

  <div class="tagCloud-tags">
      {{ range first .Site.Params.widgets.categoriesCloud.limit .Site.Taxonomies.categories.ByCount }}
          <a href="{{ .Page.RelPermalink }}" class="font_size_{{ .Count }}">
              {{ .Page.Title }}
          </a>
      {{ end }}
  </div>
</section>
  1. 修改 config.yaml
1
2
3
4
5
6
widgets:
        enabled:
            - categories
        
        categoriesCloud:
            limit: 20
  1. 网站根目录新建\i18n\zh-CN.yaml
1
2
3
4
widget:
    categoriesCloud:
        title: 
            other: 分类
  1. Download categories.svg paste to assets/icons, from here

注意:可以按需删除图标。

文章底部添加在 GitHub 上编辑此页

  1. 拷贝主题目录/layouts/partials/article/components/footer.html到网站根目录,修改为:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<footer class="article-footer">
    {{ partial "article/components/tags" . }}

    {{ if and (.Site.Params.article.license.enabled) (not (eq .Params.license false)) }}
    <section class="article-copyright">
        {{ partial "helper/icon" "copyright" }}
        <span>{{ default .Site.Params.article.license.default .Params.license | markdownify }}</span>
    </section>
    {{ end }}
	
	{{ if and (.Site.Params.article.edit.enabled) (not (eq .Params.edit false)) }}
    <section class="article-edit">
        {{ partial "helper/icon" "external-link" }}
        <span><a style="color: inherit;" href="https://github.com/iwyang/iwyang.github.io/edit/develop/content/{{ replace .File.Path "\\" "/" }}" target="_blank" rel="noopener noreferrer">在 GitHub 上编辑此页</a></span>
    </section>
    {{ end }}

    {{- if ne .Lastmod .Date -}}
    <section class="article-lastmod">
        {{ partial "helper/icon" "clock" }}
        <span>
            {{ T "article.lastUpdatedOn" }} {{ .Lastmod.Format ( or .Site.Params.dateFormat.lastUpdated "Jan 02, 2006 15:04 MST" ) }}
        </span>
    </section>
    {{- end -}}
</footer>
  1. 编辑config.yaml
1
2
3
4
5
6
7
8
9
    article:
        math: false
        toc: true
        readingTime: true 
        license:
            enabled: false
            default: Licensed under CC BY-NC-SA 4.0
        edit:
            enabled: true

以后只要在Frontmatter添加edit: false来关闭。

  1. 拷贝external-link.svg图标到网站根目录/assets/icons下。图标地址:点击直达

自动更新文章最后修改时间

1.在config.yaml里写:

1
2
3
4
5
frontmatter:
  lastmod: [":git", "lastmod", ":fileModTime", ":defalut"]    
  
enableGitInfo: true
gitRepo: "https://github.com/iwyang/hugo"
  • :git:git 文件提交修改时间
  • :fileModTime:文件修改时间
  • lastmod:文章里 lastmod 字段
  • :defalut:默认时间

config.toml里写:

[frontmatter] lastmod = [":git", “lastmod”, “:fileModTime”, “:defalut”]

enableGitInfo = true

gitRepo = “https://github.com/iwyang/hugo"

2..github/workflows/xx.yml

yml 文件中添加 2 行设置当前环境时区

1
2
3
4
5
6
name: Hugo build and deploy
on:
  push:

env:
  TZ: Asia/Shanghai # 设置当前环境时区

3.gihutb action 里 yaml 上配置

建构前新增以下配置,主要是 quotePath,默认情况下,文件名包含中文时,git 会使用引号吧文件名括起来,这会导致 action 中无法读取:GitInfo 变量,所以要设置 Disable quotePath

1
2
3
4
5
6
- name: Git Configuration
        run: |
          git config --global core.quotePath false
          git config --global core.autocrlf false
          git config --global core.safecrlf true
          git config --global core.ignorecase false

使用 checkout 的话 fetch-depth 需要设为 0,depth 默认是为 1,默认只拉取分支最近一次 commit,可能会导致一些文章的 GitInfo 变量无法获取,设为 0 代表拉去所有分支所有提交。

1
2
	uses: actions/checkout@v2
		  fetch-depth: 0   #设为0

以下是我最终的 yml 配置文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
name: GitHub Page Deploy

on:
  push:
    branches:
      - develop
      
env:
  TZ: Asia/Shanghai # 设置当前环境时区
  
jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout master
        uses: actions/checkout@v2.3.4
        with:
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod
          
      - name: Git Configuration
        run: |
          git config --global core.quotePath false
          git config --global core.autocrlf false
          git config --global core.safecrlf true
          git config --global core.ignorecase false 
          
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2.5.0
        with:
          hugo-version: 'latest'
          extended: true
          
      - name: Cache resources # 缓存 resource 文件加快生成速度
        uses: actions/cache@v2
        with:
          path: resources
         # 检查照片文件变化
          key: ${{ runner.os }}-hugocache-${{ hashFiles('content/**/*') }}
          restore-keys: ${{ runner.os }}-hugocache-             

      - name: Build Hugo
        run: hugo -v --gc --minify

      - name: Deploy Hugo to gh-pages
        uses: peaceiris/actions-gh-pages@v3.8.0
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          PUBLISH_BRANCH: master
          PUBLISH_DIR: ./public
        # cname:
        
      - name: Deploy Hugo to Server
        uses: SamKirkland/FTP-Deploy-Action@4.3.0
        with:
          server: 104.224.191.88
          username: admin
          password: ${{ secrets.FTP_MIRROR_PASSWORD }}
          local-dir: ./public/
          server-dir: /var/www/speak/

别人:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

name: Hugo build and deploy
on:
  push:

env:
  TZ: Asia/Shanghai # 设置当前环境时区

jobs:
  Actions-Hugo-Deploy:
    runs-on: ubuntu-latest
    steps:

      - name: Check out repository code
        uses: actions/checkout@v2
        with:
          submodules: recursive  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0         # Fetch all history for .GitInfo and .Lastmod

      - name: Git Configuration
        run: |
          git config --global core.quotePath false
          git config --global core.autocrlf false
          git config --global core.safecrlf true
          git config --global core.ignorecase false          
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: latest
          extended: true
      - name: Build Hugo static files
        run: hugo -v --gc --minify
      - name: Deploy to Github Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
          external_repository: Charlie-king/Charlie-king.github.io
          publish_branch: main
          publish_dir: ./public

  
      - name: NPM install
        run: npm install
      - name: Update Algolia index
        env:
          ALGOLIA_APP_ID: B6R922P6DD
          ALGOLIA_ADMIN_KEY: ${{ secrets.ALGOLIA_ADMIN_KEY }}
          ALGOLIA_INDEX_NAME: 'dev_hugo'
          ALGOLIA_INDEX_FILE: './public/index.json'
        run: npm run algolia
  

删除文章底部更新于

1
2
3
4
5
<style>
.article-footer {
    display: none;
  }
</style>

删除相关文章、分类图片,修改相关文章数目

删除相关文章图片

请在你的 article.scss 文件中找到 .related-content 这一块(大约在文件中间偏下的位置),将它完全替换为以下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
.related-content {
    overflow-x: auto;
    padding-bottom: 15px;

    &>.flex {
        float: left;
    }

    article {
        margin-right: 15px;
        flex-shrink: 0;
        overflow: hidden;
        width: 250px;
        
        /* 1. 将原本的 height: 150px 改为自适应,消除大片空白 */
        height: auto;
        min-height: 80px; /* 设置一个舒适的最小高度 */

        /* 2. 彻底隐藏图片容器 */
        .article-image {
            display: none !important;
        }

        /* 3. 新增详情区域样式:让文字在卡片中垂直/水平居中 */
        .article-details {
            padding: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            min-height: 80px;
            box-sizing: border-box;
        }

        .article-title {
            font-size: 1.6rem; /* 稍微缩小一点字号显得更精致 */
            margin: 0;
            text-align: center; /* 文字居中对齐 */
            color: var(--card-text-color-main) !important; /* 强制文字显示为主题的正常颜色 */
        }

        /* 4. 移除带图片时附带的黑色半透明渐变遮罩 */
        &.has-image {
            .article-details {
                background: transparent;
            }
        }
    }
}

删除分类图片

根目录assets/scss/partials/layout/list.scss

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.subsection-list {
    margin-bottom: var(--section-separation);
    overflow-x: auto;

    .article-list--tile {
        display: flex;
        padding-bottom: 15px;

        article {
            width: 200px; //改爲200px
            height: 50px; //改爲50px
            margin-right: 5px; //改爲5px
            flex-shrink: 0;
            box-shadow: var(--shadow-l2); //改个卡片阴影

            .article-title {
                margin: 0;
                font-size: 1.5rem; //改爲1.5rem,調整字體尺寸
            }

            .article-details {
                padding: 20px;
                justify-content: center; //添加justify-content設定,保持字體居中
            }

        }
    }
}

修改相关文章数目

根目录layouts/partials/article/components/related-contents.html

1
 {{ $related := (where (.Site.RegularPages.Related .) "Params.hidden" "!=" true) | first 3 }}  //修改数字即可

数字设为0,即关闭相关文章

加入字数统计、站点总字数统计

加入字数统计

1.直接用阅读时间改的,图标路径为根目录assets\icons

根目录layouts\partials\article\components\details.html

1
2
3
4
5
6
7
8
9
        {{ if .Site.Params.article.readingTime }}
            <div>
                {{ partial "helper/icon" "pencil" }}
                <time class="article-words">
                    {{ .WordCount }} 字
                </time>
            </div>
        {{ end }}
    </footer>

2.然后在config.yaml中加入一行,以正确显示中文字符数量

1
hasCJKLanguage: true

3.config.yaml中确保readingTime: true

站点总字数统计

1.根目录layouts\partials\footer\footer.html里写上总字数参数

1
2
3
4
{{$scratch := newScratch}}
{{ range (where .Site.Pages "Kind" "page" )}}
    {{$scratch.Add "total" .WordCount}}
{{ end }}

2.根目录layouts\partials\footer\footer.html

1
2
3
4
5
6
7
<section class="copyright">
        &copy; 
        {{ if and (.Site.Params.footer.since) (ne .Site.Params.footer.since (int (now.Format "2006"))) }}
            {{ .Site.Params.footer.since }} - 
        {{ end }}
        {{ now.Format "2006" }} Bore's Blog<br>共 {{ div ($scratch.Get "total") 1000.0 | lang.FormatNumber 2 }}k 字 · 共 {{ len (where .Site.RegularPages "Section" "post") }}篇文章</br><span><p>
    </section>

PS:如果加入站点总字数统计Github Action部署到服务器就会变慢。

添加友情链接 shortcodes

  1. 网站根目录新建文件layouts\page\links.html

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    
    {{ define "body-class" }}article-page keep-sidebar{{ end }}
    {{ define "main" }}
        {{ partial "article/article.html" . }}
    
        <div class="article-list--compact links">
            {{ $siteResources := resources }}
            {{ range $i, $link :=  $.Site.Data.links }}
                <article>
                    <a href="{{ $link.website }}" target="_blank" rel="noopener">
                        <div class="article-details">
                            <h2 class="article-title">
                                {{- $link.title -}}
                            </h2>
                            <footer class="article-time">
                                {{ with $link.description }}
                                    {{ . }}
                                {{ else }}
                                    {{ $link.website }}
                                {{ end }}
                            </footer>
                        </div>
    
                        {{ if $link.image }}
                            {{ $image := $siteResources.Get (delimit (slice "link-img/" $link.image) "") | resources.Fingerprint "md5" }}
                            {{ $imageResized := $image.Resize "120x120" }}
                            <div class="article-image">
                                <img src="{{ $imageResized.RelPermalink }}" width="{{ $imageResized.Width }}" height="{{ $imageResized.Height }}"
                                    loading="lazy" data-key="links-{{ $link.website }}" data-hash="{{ $image.Data.Integrity }}">
                            </div>
                        {{ end }}
                    </a>
                </article>
            {{ end }}
        </div>
    
        {{ if or (not (isset .Params "comments")) (eq .Params.comments "true")}} 
            {{ partial "comments/include" . }}
        {{ end }}
    
        {{ partialCached "footer/footer" . }}
    
        {{ partialCached "article/components/photoswipe" . }}
    {{ end }}
    
  2. 网站根目录新建文件\layouts\shortcodes\link.html

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    {{$URL := .Get 0}}
    {{ with .Site.GetPage $URL }}
    <div class="post-preview">
      <div class="post-preview--meta" style="width:100%;">
        <div class="post-preview--middle">
          <h4 class="post-preview--title">
            <a target="_blank" href="{{ .Permalink }}">{{ .Title }}</a>
          </h4>
          <time class="post-preview--date">{{ .Date.Format ( default "2006-01-02") }}</time>
          {{ if .Params.tags }}
          <small>{{ range .Params.tags }}#{{ . }}&nbsp;{{ end }}</small>
          {{ end }}
          <section style="max-height:105px;overflow:hidden;" class="post-preview--excerpt">
            {{ .Summary | plainify}}
          </section>
        </div>
      </div>
    </div>
    {{ end }}
    
    1. 网站图像放在网站根目录\assets\link-img\文件夹下。
    2. 网站根目录新建文件\data\links.json
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    
    [
        {
            "title": "Upptime",
            "website": "https://iwyang.github.io/check",
            "image": "upptime.jpg",
    		"description": "利用Github Actions查看网站运行状态。"
        },
    	{
            "title": "ConstOwn",
            "website": "https://blog.juanertu.com",
            "image": "constown.jpg",
    		"description": "能与你一起成长,我荣幸之至。"
        },
        {
            "title": "小丁的个人博客",
            "website": "https://tding.top",
            "image": "ding.jpg",
    		"description": "世间所有的相遇,都是久别重逢。"
        },
        {
            "title": "Xu's Blog",
            "website": "https://hasaik.com",
            "image": "xu.jpg",
    		"description": "简单不先于复杂,而是在复杂之后。"
        },
        {
            "title": "知行志",
            "website": "https://baozi.fun",
            "image": "zhi.jpg",
    		"description": "Halo Theme Xue作者。"
        },
        {
            "title": "Takagi",
            "website": "https://lixingyong.com",
            "image": "takagi.jpg",
    		"description": "Takagi是啥呀??当然是最喜欢的Takagi了吖ヾ(≧∇≦*)ゝ"
        },
        {
            "title": "千与千寻",
            "website": "https://www.chihiro.org.cn",
            "image": "qian.jpg",
    		"description": "所以,看不到光,算是不幸吗?需要光才是真正的不幸吧。"
        },
        {
            "title": "Bill Yang's Blog",
            "website": "https://blog.bill.moe",
            "image": "bill.jpg",
    		"description": "这辈子都不可能更新的 。"
        },
        {
            "title": "Sanarous's Blog",
            "website": "https://bestzuo.cn",
            "image": "sanarous.jpg",
    		"description": "Dream it possible, make it possible"
        },
    	    {
            "title": "JACK小桔子的小屋",
            "website": "https://jackxjz.top/",
            "image": "jack.jpg",
    		"description": "一个分享科技/日常的网站。"
        },
    	{
            "title": "若只如初见",
            "website": "https://joyli.net.cn/",
            "image": "ruo.jpg",
    		"description": "世间所有的相遇,都是久别重逢。"
        },
    		{
            "title": "大大的小蜗牛",
            "website": "https://eallion.com/",
            "image": "eallion.jpg",
    		"description": "机会总是垂青于有准备的人。"
        }
    ]
    

5.调整布局,设置友情链接为双栏:

修改根目录/assets/scss/custom.scss

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
//友情链接双栏
@media (min-width: 1024px) {
    .article-list--compact.links {
        display: grid;
        grid-template-columns: 1fr 1fr;
        background: none;
        box-shadow: none;
        
        article {
            background: var(--card-background);
            border: none;
            box-shadow: var(--shadow-l2);
            margin-bottom: 8px;
            border-radius: 10px;
            &:nth-child(odd) {
                margin-right: 8px;
            }
        }
    }
}

添加音乐短代码

网易音乐

1.网站根目录新建文件layouts\shortcodes\music.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{{- $scratch := .Page.Scratch.Get "scratch" -}}
<!-- require APlayer -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
<style type="text/css">.dark-theme .aplayer{background:#212121}.dark-theme .aplayer.aplayer-withlist .aplayer-info{border-bottom-color:#5c5c5c}.dark-theme .aplayer.aplayer-fixed .aplayer-list{border-color:#5c5c5c}.dark-theme .aplayer .aplayer-body{background-color:#212121}.dark-theme .aplayer .aplayer-info{border-top-color:#212121}.dark-theme .aplayer .aplayer-info .aplayer-music .aplayer-title{color:#fff}.dark-theme .aplayer .aplayer-info .aplayer-music .aplayer-author{color:#fff}.dark-theme .aplayer .aplayer-info .aplayer-controller .aplayer-time{color:#eee}.dark-theme .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon path{fill:#eee}.dark-theme .aplayer .aplayer-list{background-color:#212121}.dark-theme .aplayer .aplayer-list::-webkit-scrollbar-thumb{background-color:#999}.dark-theme .aplayer .aplayer-list::-webkit-scrollbar-thumb:hover{background-color:#bbb}.dark-theme .aplayer .aplayer-list li{color:#fff;border-top-color:#666}.dark-theme .aplayer .aplayer-list li:hover{background:#4e4e4e}.dark-theme .aplayer .aplayer-list li.aplayer-list-light{background:#6c6c6c}.dark-theme .aplayer .aplayer-list li .aplayer-list-index{color:#ddd}.dark-theme .aplayer .aplayer-list li .aplayer-list-author{color:#ddd}.dark-theme .aplayer .aplayer-lrc{text-shadow:-1px -1px 0 #666}.dark-theme .aplayer .aplayer-lrc:before{background:-moz-linear-gradient(top, #212121 0%, rgba(33,33,33,0) 100%);background:-webkit-linear-gradient(top, #212121 0%, rgba(33,33,33,0) 100%);background:linear-gradient(to bottom, #212121 0%, rgba(33,33,33,0) 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#212121', endColorstr='#00212121',GradientType=0 )}.dark-theme .aplayer .aplayer-lrc:after{background:-moz-linear-gradient(top, rgba(33,33,33,0) 0%, rgba(33,33,33,0.8) 100%);background:-webkit-linear-gradient(top, rgba(33,33,33,0) 0%, rgba(33,33,33,0.8) 100%);background:linear-gradient(to bottom, rgba(33,33,33,0) 0%, rgba(33,33,33,0.8) 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#00212121', endColorstr='#cc212121',GradientType=0 )}.dark-theme .aplayer .aplayer-lrc p{color:#fff}.dark-theme .aplayer .aplayer-miniswitcher{background:#484848}.dark-theme .aplayer .aplayer-miniswitcher .aplayer-icon path{fill:#eee}</style>
<script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<!-- require MetingJS -->
<script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script>

{{- if .IsNamedParams -}}
    {{- if .Get "url" -}}
        <meting-js url="{{ .Get `url` }}" name="{{ .Get `name` }}" artist="{{ .Get `artist` }}" cover="{{ .Get `cover` }}" theme="{{ .Get `theme` | default `#2980b9` }}"
        {{- with .Get "fixed" }} fixed="{{ . }}"{{ end -}}
        {{- with .Get "mini" }} mini="{{ . }}"{{ end -}}
        {{- with .Get "autoplay" }} autoplay="{{ . }}"{{ end -}}
        {{- with .Get "volume" }} volume="{{ . }}"{{ end -}}
        {{- with .Get "mutex" }} mutex="{{ . }}"{{ end -}}
        ></meting-js>
    {{- else if .Get "auto" -}}
        <meting-js auto="{{ .Get `auto` }}" theme="{{ .Get `theme` | default `#2980b9` }}"
        {{- with .Get "fixed" }} fixed="{{ . }}"{{ end -}}
        {{- with .Get "mini" }} mini="{{ . }}"{{ end -}}
        {{- with .Get "autoplay" }} autoplay="{{ . }}"{{ end -}}
        {{- with .Get "loop" }} loop="{{ . }}"{{ end -}}
        {{- with .Get "order" }} order="{{ . }}"{{ end -}}
        {{- with .Get "volume" }} volume="{{ . }}"{{ end -}}
        {{- with .Get "mutex" }} mutex="{{ . }}"{{ end -}}
        {{- with .Get "list-folded" }} list-folded="{{ . }}"{{ end -}}
        {{- with .Get "list-max-height" }} list-max-height="{{ . }}"{{ end -}}
        ></meting-js>
    {{- else -}}
        <meting-js server="{{ .Get `server` }}" type="{{ .Get `type` }}" id="{{ .Get `id` }}" theme="{{ .Get `theme` | default `#2980b9` }}"
        {{- with .Get "fixed" }} fixed="{{ . }}"{{ end -}}
        {{- with .Get "mini" }} mini="{{ . }}"{{ end -}}
        {{- with .Get "autoplay" }} autoplay="{{ . }}"{{ end -}}
        {{- with .Get "loop" }} loop="{{ . }}"{{ end -}}
        {{- with .Get "order" }} order="{{ . }}"{{ end -}}
        {{- with .Get "volume" }} volume="{{ . }}"{{ end -}}
        {{- with .Get "mutex" }} mutex="{{ . }}"{{ end -}}
        {{- with .Get "list-folded" }} list-folded="{{ . }}"{{ end -}}
        {{- with .Get "list-max-height" }} list-max-height="{{ . }}"{{ end -}}
        ></meting-js>
    {{- end -}}
{{- else if strings.HasSuffix (.Get 0) "http" -}}
    <meting-js auto="{{ .Get 0 }}" theme="#2980b9"></meting-js>
{{- else -}}
    <meting-js server="{{ .Get 0 }}" type="{{ .Get 1 }}" id="{{ .Get 2 }}" theme="#2980b9"></meting-js>
{{- end -}}
{{- $scratch.Set "music" true -}}

2.添加歌曲列表(注意:去掉注释/* */)

1
{{/* < music auto="https://music.163.com/#/playlist?id=60198"> */}}

3.添加单曲(注意:去掉注释/* */)

1
2
3
{{/* < music server="netease" type="song" id="1868553" > */}}
或者
{{/* < music netease song 1868553 > */}}

4.其它参数

music shortcode 有一些可以应用于以上三种方式的其它命名参数:

  • autoplay [可选]

    是否自动播放音乐, 默认值是 false.

本地音乐

1.新建layouts/_shortcodes/audio.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{{- $name := .Get 0 -}}
{{- $title := .Get "title" | default $name -}}

{{/* 核心:尝试从当前文章资源中匹配该文件 */}}
{{- $audio := .Page.Resources.GetMatch $name -}}
{{- $src := "" -}}

{{- if $audio -}}
    {{- $src = $audio.RelPermalink -}}
{{- else -}}
    {{/* 如果找不到,则视为 static 目录下的绝对路径 */}}
    {{- $src = $name | safeURL -}}
{{- end -}}

<div class="local-audio-wrapper" style="margin: 20px 0; background: var(--card-background); padding: 15px; border-radius: var(--card-border-radius); box-shadow: var(--shadow-l2);">
    <div class="audio-title" style="font-size: 14px; color: var(--card-text-color-main); margin-bottom: 10px; font-weight: bold; display: flex; align-items: center; gap: 8px;">
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="18" cy="16" r="3"></circle></svg>
        <span>{{ $title }}</span>
    </div>
    <audio controls preload="metadata" style="width: 100%; height: 40px;">
        <source src="{{ $src }}" type="audio/mpeg">
        </audio>
</div>

2.使用方法

  • 基础用法(自动匹配文件名):

    1
    
    hefeng.mp3
  • 进阶用法(自定义显示标题):

    1
    
    我的收藏 - 和风物语

更改分类、标签、页面显示中文

  1. content目录下新建categories\_index.md:
1
2
3
---
title: "分类"
---
  1. content目录下新建tags\_index.md:
1
2
3
---
title: "标签"
---
  1. 根目录\i18n\zh-CN.yaml输入:
1
2
3
4
list:
    page:
        one: "{{ .Count }} 页面"
        other: "{{ .Count }} 页面"

最终根目录\i18n\zh-CN.yaml

1
2
3
4
5
6
7
8
9
list:
    page:
        one: "{{ .Count }} 页面"
        other: "{{ .Count }} 页面"

widget:
    categoriesCloud:
        title: 
            other: 分类

hugo添加说说

添加说说:https://github.com/iwyang/iwyang.github.io/blob/develop/layouts/shuoshuo/list.html

首页轮播:https://github.com/iwyang/iwyang.github.io/blob/develop/layouts/home.html

CSS:https://github.com/iwyang/iwyang.github.io/blob/develop/assets/scss/custom.scss

这份“终极保姆级手册”已经非常完善了!结合我们最后确认的**“Token 常量化安全方案”以及“区分变量类型”**的细节,我为你对第二步和第三步进行了优化修改。

这样修改后,既保证了你以后操作不用每次都粘贴 Token,又防止了 DIR_NAME 错误弹出输入框,彻底实现了“一劳永逸”。

以下是为你修改和升级后的**“安卓发布说说终极版执行手册”**,你可以直接把这份文档存进你的博客或者备忘录里:


安卓一键发布 Hugo 说说 (HTTP Shortcuts 终极版)

经历了乱码、路径报错和 Token 安全问题,这份手册将所有经验融会贯通,制定了**“绝对避坑、零报错、完美中文显示、Token高安全”**的终极执行方案。

请清空之前的设置(或者新建一个快捷方式),我们从零开始,一步步拿下它!


🚨 第一步:获取全新的 GitHub Token(安全第一)

为了你的仓库安全,避免明文泄露,请务必先做这一步

  1. 登录 GitHub ➔ SettingsDeveloper settingsPersonal access tokens (classic)
  2. 找到旧的 Token(如果有暴露过),点击 Delete 彻底删除。
  3. 点击 Generate new token (classic),勾选 repo 权限,生成一个新的。
  4. 复制新 Token,保存在手机备忘录里备用,千万不要在截图或视频中发出来。

🛠️ 第二步:建立 6 个变量(分类建立,杜绝乱码与泄露)

打开 HTTP Shortcuts App,点击底部中间的 { } 图标。我们需要分三种类型建立 6 个变量。

1. 创建5 个“输入文本 (Input Text)”变量

依次点击 + ➔ 选择 输入文本,创建以下三个:

  • 变量 1名称INPUT_FILENAME | 对话框标题1. 请输入文件名

  • ⚠️ 避坑关键:在“高级设置”中,绝对不要勾选“JSON 编码”

  • 变量 2名称INPUT_TAGS | 对话框标题2. 输入标签 (逗号隔开)

  • ⚠️ 避坑关键不要勾选“JSON 编码”

  • 变量 3名称INPUT_CONTENT | 对话框标题3. 记录此刻的闪念...

  • ⚠️ 避坑关键务必勾选“多行”不要勾选“JSON 编码”

  • 变量 4名称DIR_NAME

  • ⚠️ 避坑关键不要勾选“JSON 编码”

  • 变量 5名称BASE64_CONTENT

  • ⚠️ 避坑关键务必勾选“多行”不要勾选“JSON 编码”

2. 创建 1 个“常量 (Constant)”(保护 Token 安全)

回到变量列表,点击 + ➔ 选择 常量

  • 变量 6名称MY_GITHUB_TOKEN
  • 值 (Value):直接粘贴你刚才生成的 ghp_ 开头的新 Token。(记得勾选将值视为密文)
  • (这样以后无论你怎么截图分享配置,Token 都被隐藏在这个变量里了,极度安全且不用每次手动输入)

🚀 第三步:配置快捷方式(核心组装)

回到 App 首页,点击 +新建快捷方式

1. 植入终极查表法脚本

点击 脚本编写在执行前运行 JavaScript完整粘贴这段“手动挡”无敌代码(完全不依赖系统内置函数,彻底告别中文乱码):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
const nameInput = getVariable('INPUT_FILENAME');
const tagsInput = getVariable('INPUT_TAGS');
const contentInput = getVariable('INPUT_CONTENT');

let tagLine = '""';
if (tagsInput) {
    const tags = tagsInput.split(/[,,]/).map(t => `"${t.trim()}"`).filter(t => t !== '""');
    if (tags.length > 0) tagLine = tags.join(', ');
}

const now = new Date();
const isoTime = new Date(now.getTime() + 8*60*60000).toISOString().replace("Z", "+08:00");
const dir = nameInput ? nameInput.trim() : ("bb-" + now.getTime());
const slug = Math.random().toString(36).substring(2, 10);

const fm = [
    "---",
    `title: "${dir}"`,
    `slug: "${slug}"`,
    'description: ""',
    `date: ${isoTime}`,
    `lastmod: ${isoTime}`,
    "draft: false",
    "toc: true",
    "weight: false",
    'image: ""',
    'categories: [""]',
    `shuoshuotags: [${tagLine}]`,
    "---",
    contentInput
].join('\n');

// 完全手动实现 UTF-8 + Base64,不依赖任何内置函数
function encodeBase64UTF8(str) {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    // 第一步:字符串转 UTF-8 字节数组
    const bytes = [];
    for (let i = 0; i < str.length; i++) {
        let code = str.charCodeAt(i);
        // 处理 emoji 等4字节字符(代理对)
        if (code >= 0xD800 && code <= 0xDBFF) {
            const hi = code;
            const lo = str.charCodeAt(++i);
            code = ((hi - 0xD800) << 10) + (lo - 0xDC00) + 0x10000;
        }
        if (code < 0x80) {
            bytes.push(code);
        } else if (code < 0x800) {
            bytes.push(0xC0 | (code >> 6));
            bytes.push(0x80 | (code & 0x3F));
        } else if (code < 0x10000) {
            bytes.push(0xE0 | (code >> 12));
            bytes.push(0x80 | ((code >> 6) & 0x3F));
            bytes.push(0x80 | (code & 0x3F));
        } else {
            bytes.push(0xF0 | (code >> 18));
            bytes.push(0x80 | ((code >> 12) & 0x3F));
            bytes.push(0x80 | ((code >> 6) & 0x3F));
            bytes.push(0x80 | (code & 0x3F));
        }
    }
    // 第二步:字节数组转 Base64
    let result = '';
    for (let i = 0; i < bytes.length; i += 3) {
        const b0 = bytes[i], b1 = bytes[i+1] || 0, b2 = bytes[i+2] || 0;
        result += chars[b0 >> 2];
        result += chars[((b0 & 3) << 4) | (b1 >> 4)];
        result += i+1 < bytes.length ? chars[((b1 & 15) << 2) | (b2 >> 6)] : '=';
        result += i+2 < bytes.length ? chars[b2 & 63] : '=';
    }
    return result;
}

setVariable('DIR_NAME', dir);
setVariable('BASE64_CONTENT', encodeBase64UTF8(fm));

2. 配置无错 URL(基本设置)

点击 基本设置

  • 方法:改成 PUT
  • URL:手动输入 https://api.github.com/repos/iwyang/iwyang.github.io/contents/content/shuoshuo/
  • ⚠️ 避坑关键:输入到这里时,点击键盘上方的 { } 按钮,从列表里选择 DIR_NAME,然后再接着输入 /index.md
  • 最终看起来应该是:.../shuoshuo/{DIR_NAME}/index.md(确保 {DIR_NAME} 是被识别的高亮变量块,绝不能是手动敲打的 %7B...)。

3. 配置认证(请求头 - 安全升级版)

点击 请求头 ➔ 点击 +

  • 第一行 ➔ 键:Authorization | 值:输入 Bearer (注意后面有一个空格),然后点击右侧的 { } 按钮,选择你刚刚创建的常量变量 MY_GITHUB_TOKEN

  • *最终效果:Bearer {MY_GITHUB_TOKEN}*

  • 第二行 ➔ 键:Accept | 值:application/vnd.github.v3+json

4. 配置防 422 报错(请求体)

点击 请求体/请求参数

  • 类型:选择 自定义类型
  • 内容类型:填入 application/json
  • 正文:严格按照下面的格式敲。输入 {BASE64_CONTENT} 时,务必点击右侧的 { } 按钮插入,不能手动打大括号!
1
2
3
4
{
  "message": "feat: 新增说说 via Android",
  "content": "{BASE64_CONTENT}"
}

🎉 第四步:保存与终极测试

  1. 点击右上角的 确认保存。
  2. 将这个快捷方式添加到桌面。
  3. 点击运行测试:
  • 框1填:测试终极版
  • 框2填:成功, 完结撒花
  • 框3填:这段查表法 Base64 代码太牛了,彻底告别乱码!😎
  1. 如果你看到手机底部弹出执行成功(或状态码 201),恭喜你!去你的博客上刷新看看吧:完美的中文显示、完美的 Page Bundle 目录结构、极度安全的 Token 隔离,全部搞定!

附:使用Git Submodule管理Hugo主题

  • 如果克隆库的时候要初始化子模块,请加上 --recursive 参数,如:
1
git clone -b develop git@github.com:iwyang/iwyang.github.io.git blog --recursive
  • 如果已经克隆了主库但没初始化子模块,则用:
1
git submodule update --init --recursive
  • 如果已经克隆并初始化子模块,而需要从子模块的源更新这个子模块,则:
1
git submodule update --recursive --remote

更新之后主库的 git 差异中会显示新的 SHA 码,把这个差异选中提交即可。


  • 其他命令:在主仓库更新所有子模块:git submodule foreach git pull origin master

附:hugo注释

1
{{/* comment */}}

参考链接

编辑此页 | #c3436e8
最近更新:--| #9432357
使用 Hugo 构建 | 主题 StackJimmy 设计