2月2号原域名过期了,讨厌通过一个域名就能开盒到自己的名字、邮箱,索性换了一个域名,同时把博客重新整理一下。

兜兜转转,显示hexo + vercel + github图床方案,觉得写作体验不好,使用elog集成了Flowus写作,然后Flowus导出文章的时候图片总出问题,转了Notion。最后转的格式也是不尽人意。加上还更换过好几个主题试了试,导致了不少文章中的格式错乱,甚至图片丢失(主要是使用elog从Flowus导出时出的问题)。自己也没做好备份,以前搭建的很多东西配置和数据也丢了,新的一年,不再做数据的亡命徒了。。。

最后选择hugo的原因,还是生成静态网页速度快,同时PaperMod主题的简洁、速度快吸引了我。Paper主题在5年前已经停更了,PaperMod主题基于Paper主题,希望在其基础上添加更多的feature,现在还在更新,现在看到的上一个commit是4天前。

主题还是有些不尽人意的地方,比如:toc功能只在顶部,非常影响阅读体验;不支持latex公式;封面导致首页文章磁贴直接变大,影响美观;缺少图片放大预览;js、css加载优化等。

添加latex公式支持

参考:Hugo博客LaTeX渲染 - 草祭

MathJaxKaTeX两种解决方案,MathJax使用的bootcss的cdn,加载速度有点慢,应该可以使用其他cdn优化一下速度,没研究。KaTex的加载速度会更快一点。

公式测试:$E=mc^2$

KaTex

编辑layouts/partials/math.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<!-- KaTeX -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.10.0-rc.1/katex.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.10.0-rc.1/katex.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.10.0-rc.1/contrib/auto-render.min.js"></script>

<script>
    document.addEventListener("DOMContentLoaded", function() {
      renderMathInElement(document.body, {
              delimiters: [
                  {left: "$$", right: "$$", display: true},
                  {left: "$", right: "$", display: false}
              ]
          });
    });
</script>

添加math.html导入:

编辑layouts/partials/extend_head.html,添加一行

1
{{ partial "mathjax.html" . }}

MathJax

 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
<script type="text/javascript" async
    src="https://cdn.bootcss.com/mathjax/2.7.3/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
        MathJax.Hub.Config({
            tex2jax: {
                inlineMath: [['$', '$'], ['\\(', '\\)']],
                displayMath: [['$$', '$$'], ['\[\[', '\]\]']],
                processEscapes: true,
                processEnvironments: true,
                skipTags: ['script', 'noscript', 'style', 'textarea', 'pre'],
                TeX: {
                    equationNumbers: { autoNumber: "AMS" },
                    extensions: ["AMSmath.js", "AMSsymbols.js"]
                }
            },
            "HTML-CSS": {
                availableFonts: ["Arial", "TeX"],
                preferredFont: "TeX",
                webFont: "TeX"
            }
        });

        MathJax.Hub.Queue(function () {
            // Fix <code> tags after MathJax finishes running. This is a
            // hack to overcome a shortcoming of Markdown. Discussion at
            // https://github.com/mojombo/jekyll/issues/199
            var all = MathJax.Hub.getAllJax(), i;
            for (i = 0; i < all.length; i += 1) {
                all[i].SourceElement().parentNode.className += ' has-jax';
            }
        });
    </script>

<style>
    code.has-jax {
        font: inherit;
        font-size: 100%;
        background: inherit;
        border: inherit;
        color: #515151;
    }
</style>

文章自动编号

参考:PaperMod主题优化 | 向着悠远的苍穹

  1. 编辑themes/PaperMod/layouts/_default/single.html

    1
    2
    3
    
    <article class="post-single">
    <!-- 替换为 -->
    <article class="post" autonumbering>
    
  2. 编辑assets/css/extended/blank.css,添加下面代码

     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
    
    /* ========= 文章和目录自动编号(从二级标题开始)============ */
    body {
        counter-reset: h2
    }
    
    h2 {
        counter-reset: h3
    }
    
    h3 {
        counter-reset: h4
    }
    
    h4 {
        counter-reset: h5
    }
    
    article[autonumbering] h2:before {
        counter-increment: h2;
        content: counter(h2) ". "
    }
    
    article[autonumbering] h3:before {
        counter-increment: h3;
        content: counter(h2) "." counter(h3) " "
    }
    
    article[autonumbering] h4:before {
        counter-increment: h4;
        content: counter(h2) "." counter(h3) "." counter(h4) " "
    }
    
    article[autonumbering] .toc ul {
        counter-reset: item
    }
    
    article[autonumbering] .toc li a:before {
        content: counters(item, ".") " ";
        counter-increment: item
    } 
    

侧边目录

唯一遗憾的是手机端支持不是很好,右下角能有个按钮展开目录最好不过了。

参考:Hugo侧边目录 | 3rd’s Blog

toc.html

编辑layouts/partials/toc.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
 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
{{- $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 }}

css

编辑assets/css/extended/blank.css

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

封面图片缩小并移到侧边

image-20250213220438322

  1. 编辑layouts/_default/list.html,添加一个 class 标识,命名为post-info,把 entry-header 和 entry-content 和 entry-footer 都包裹进去,具体修改如下:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    <article class="{{ $class }}">
      <div class="post-info">
        <header class="entry-header">
          <h2>
            {{- .Title }}
            {{- if .Draft }}<sup><span class="entry-isdraft">&nbsp;&nbsp;[draft]</span></sup>
            {{- end }}
          </h2>
        </header>
        {{- if (ne (.Param "hideSummary") true) }}
        <div class="entry-content">
          <p>{{ .Summary | plainify | htmlUnescape }}{{ if .Truncated }}...{{ end }}</p>
        </div>
        {{- end }}
        {{- if not (.Param "hideMeta") }}
        <footer class="entry-footer">
          {{- partial "post_meta.html" . -}}
        </footer>
        {{- end }}
      </div>
      {{- $isHidden := (.Site.Params.cover.hidden | default .Site.Params.cover.hiddenInList) }}
      {{- partial "cover.html" (dict "cxt" . "IsHome" true "isHidden" $isHidden) }}
      <a class="entry-link" aria-label="post link to {{ .Title | plainify }}" href="{{ .Permalink }}"></a>
    </article>
    
  2. 编辑assets/css/extended/blank.css,添加如下代码

     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
    
    /* 封面图片显示到右边 */
    .entry-cover1 {
        border-radius: 10px;
        display: flex;
        justify-content: center;
    }
    
    .post-entry {
        display: flex;
        flex-direction: row;
        align-items: center;
    }
    
    .entry-cover {
        border-radius: 10px;
        overflow: hidden;
        width: 50%;
        margin-bottom: unset;
    
        max-height: 150px;
        display: grid;
        align-content: center;
    }
    
    .post-info {
        display: inline-block;
        overflow: hidden;
        width: 100%;
        padding-right: 10px;
    }
    
    /* 文章内使用的封面图 */
    .entry-cover1 img {
        border-radius: var(--radius);
        pointer-events: none;
        width: 100%;
        height: auto;
        margin-bottom: 40px;
    }
    

代码使用JetBrains Mono字体

  1. 编辑layouts/partials/extend_head.html,添加:

    1
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jetbrains-mono@1.0.6/css/jetbrains-mono.min.css" />
    
  2. 编辑assets/css/extended/blank.css,添加:

    1
    2
    3
    
    code {
        font-family: "JetBrains Mono", sans-serif;
    }
    

修改post_meta头部信息

image-20250213220356173

编辑layouts/partials/post_meta.html,粘贴如下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{{- $scratch := newScratch }}

{{- if not .Date.IsZero -}}
{{- $scratch.Add "meta" (slice (printf "📅 发布时间:&nbsp;<span title='%s'>%s</span>" (.Date) (.Date | time.Format (default "January 2, 2006" site.Params.DateFormat)))) }}
{{- end }}

{{- if (.Param "ShowWordCounts") -}}
{{- $scratch.Add "meta" (slice (default (printf "📝 字数:&nbsp;%d字" .WordCount))) }}
{{- end }}

{{- if (.Param "ShowReadingTime") -}}
{{- $scratch.Add "meta" (slice (default (printf "⏱️ 时长: %d分钟" .ReadingTime))) }}
{{- end }}

{{- with (partial "author.html" .) }}
{{- $scratch.Add "meta" (slice (printf "🚀&nbsp;%s" (.))) }}
{{- end }}

{{- with ($scratch.Get "meta") }}
{{- delimit . "&nbsp;|&nbsp;" | safeHTML -}}
{{- end -}}

图片处理

对于图片的处理是个头疼的问题,以我博客当前的体量(整个打包,一起还没15M),整一个图床纯多余,增加运维成本。(之前使用过蓝空图床,但数据库使用123456当root密码还暴露在公网下,被删数据了。。。)

image-20250213221302137

最理想的情况下,应该和博客在一个项目下。

参考:

  1. 使用typora更好更快地写hugo博客 | 杂烩饭

  2. 使用vscode来写hugo博客并处理图片插入问题 | 杂烩饭

我将图片放在了static/images/post/目录下,希望粘贴的图片能自动复制到文件夹里,在markdown文件中,使用![](/images/post/)的格式,同时,编辑软件能正确显示,对于typora,在Front Matter中添加如下两行即可:

1
2
typora-root-url: ../../static
typora-copy-images-to: ../../static/images/post

同时为了新文章能够自动添加该Front Matter,可以在archetypes/default.md中添加上面两行。

添加Twikoo评论

hugo.yaml配置文件中,设置params -> commentstrue,修改layouts/partials/comments.html,粘贴如下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!-- Twikoo -->
<div>
    <div class="pagination__title">
        <span class="pagination__title-h" style="font-size: 20px;"><i class="fas fa-comments fa-fw" style="margin-right: 10px;"></i>评论</span>
        <hr />
    </div>
    <div id="tcomment"></div>
    <script src="https://gcore.jsdelivr.net/npm/twikoo@{{ .Site.Params.twikoo.version }}/dist/twikoo.all.min.js"></script>
    <script>
        twikoo.init({
            envId: "{{ .Site.Params.twikoo.envId }}",
            el: "#tcomment",
            lang: 'zh-CN'
        });
    </script>
</div>

接着在hugo.yaml的的params配置中添加twikoo配置,如:

1
2
3
4
5
params:
  ...
  twikoo:
    version: 1.6.8
    envId: https://comment.imbai.xin

添加友链

找不到样式的参考链接了,等找到了再补上吧。

image-20250214143759154

  1. 新建一个shortcodes,编辑layouts/shortcodes/friends.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
     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
    
    <style>
      .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;
        }
      }
    </style>
    
    {{ range .Site.Data.friends }}
    
    <a target="_blank" href={{ .link }} title={{ .name }} class="friendurl">
      <div class="frienddiv">
        <div class="frienddivleft">
          <img class="myfriend" src={{ .logo }} />
        </div>
        <div class="frienddivright">
          <div class="friendname">{{ .name }}</div>
          <div class="friendinfo">{{ .desc }}</div>
        </div>
      </div>
    </a>
    
    {{ end }}
    
  2. 创建友链数据文件,编辑data/friends.yaml,格式如下:

    1
    2
    3
    4
    
    - name: "道宣的窝"
      desc: "道宣的窝"
      link: "http://daoxuan.cc/"
      logo: "https://picture.daoxuan.cc/image/202301301254377.webp"
    
  3. 创建content/friend/index.md文件,粘贴如下内容:

    1
    2
    3
    4
    5
    
    ---
    title: "🤝 朋友们"
    ---
    
    {{< friends >}}