如你所见,目前博客有了亿亿点小变化,总之是在 PaperMod 主题上东改改西抄抄。

本来标题是叫优化 PaperMod 主题的,但细想还是叫魔改更合适这些改动。

一、使用霞鹜文楷字体

这个字体怎么样,好看吧~

字体项目 ,这里我们使用 CDN 引入。

1.在 Hugo 项目根目录下的 layouts/partials/extend_head.html,新建/追加:

<!-- 引入霞鹜文楷字体 -->
<link rel="stylesheet" href="https://npm.elemecdn.com/[email protected]/lxgwwenkaiscreen.css" integrity="sha384-JSVn1znHuc8FVDp6lnwfdr+E/15Rtb/gBqsVMICU1fX4qsG81cPVTaneaJWFM8Ox" crossorigin="anonymous" media="print" onload="this.media='all'">

这里我用了 SRI 来预防 CDN 投毒,版本不一样的注意重新生成 SRI

2.在 Hugo 项目根目录下的 assets/css/extended/fonts.css,新建/追加:

/* 使用霞鹜文楷字体 */
body,  
.post-content code {  
  font-family: "LXGW WenKai Screen", "Roboto", "PingFang SC", "Microsoft Yahei", sans-serif;  
}  

参考 PaperMod 主题引用“霞鹜文楷”字体

二、让站外链接从新窗口打开

默认站外链接都是当前页打开,对留存率很不友好呀,而且站外链接通常是补充文章内容的,需要返回回来很打断节奏。

1.在 Hugo 项目根目录下的 layouts/default/_markup/render-link.html,新建/追加:

<!-- 让站外链接统统是新窗口打开 -->
<a href="{{ .Destination | safeURL }}"
  {{- with .Title }} title="{{ . }}"{{ end -}}
  {{- if not (in .Destination "yuk7.com") }} target="_blank"{{ end -}}
>
  {{- with .Text | safeHTML }}{{ . }}{{ end -}}
</a>

参考 Hugo 设置外部链接用新窗口打开

三、目录侧边展示

PaPerMod 主题自带的目录只能在文章顶部,跳转只能拉回最上面,放在侧边跟随就方便多啦。

1.在 Hugo 项目根目录下的 layouts/partials/toc.html,新建/追加:

{{- $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 }}

2.在 Hugo 项目根目录下的 assets/css/extended/blank.css,新建/追加:

/* 文章目录放在侧边的css 开始 */
: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);
}

/* 文章目录放在侧边的css 结束 */

3,修改 Hugo 项目根目录下 config.yml 中的目录配置,启用目录。

params:
  UseHugoToc: true
  showtoc: true
  tocopen: true

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

四、添加 Umami 网站统计

搭建教程直接跟着参考走,这里不多赘述。

回想起来网站统计也是换了好几个平台过了,从最开始用的百度统计,到用 Cloudflare 的,到现在的自建 Umami。

其实最开始的百度统计挺好用的,不过那都好几年前的了,有回忆美化滤镜加成。

然后就是直接用的 Cloudflare DNS 提供的,但是免费版基本没法用,数据没法参考。

现在自建的 Umami 目前用起来还行,对访客隐私友好,但是如果你和我一样域名 DNS 是在 Cloudflare 上的话,需要额外的设置一下,规则>>转换规则>>打开“添加访问者位置标头”,这样 Umami 才能统计到具体的省份城市。

魔改PaperMod主题和博客改动-20240814120924293

参考 0 成本自建网站统计:Umami+VercelCities and regions are not being recorded · Issue #2682 · umami-software/umami · GitHub

五、文章元素修改样式

感觉在整体主题颜色单调的基调上这样蓝色样式还挺好看的,顺带改了下图片和代码块显示。

1.在 Hugo 项目根目录下的 assets/css/extended/blank.css,新建/追加:

/* 文章图片居中 */
.post-content img {
    margin: auto;
}
/* 文章&评论图片和代码块四角圆滑 */
.post-single img,
.post-content pre {
    border-radius: 0.3em;
}
/* 文章超链接蓝底样式 */
.post-content a:not(.anchor) {
    box-shadow: none;
    text-decoration: none;
    background: linear-gradient(to bottom, transparent 70%, rgba(49,184,204,0.5) 70%);
}

六、添加 favicon

1.这个就直接 favicon.io 生成的,图片文件放在在 Hugo 项目根目录下的 static 下面即可。

2.修改 Hugo 项目根目录下 config.yml 中的 favicon 配置:

params:
  assets:
    favicon: "/favicon.ico"
    favicon16x16: "/favicon-16x16.png"
    favicon32x32: "/favicon-32x32.png"
    apple_touch_icon: "/apple-touch-icon.png"
    safari_pinned_tab: "/favicon-16x16.png"

挺喜欢这个流星🌠的,跟主页描述的🌟也是对应上了。

七、让代码区跟随日夜主题切换

PaperMod 主题自带日夜主题切换,可是代码框却只有一套样式,白天还是黑框框,很丑啊,忍不了必须出手!

我在 monokailightmonokai 基础上修改了一些颜色

1.在 Hugo 项目根目录下的 assets/css/extended/chroma-light.css,新建/追加:

/* Background */ .bg { color:#272822;background-color:#fafafa; }
/* PreWrapper */ .chroma { color:#272822;background-color:#fafafa; }
/* Other */ .chroma .x {  }
/* Error */ .chroma .err { color:#e769ac; }
/* CodeLine */ .chroma .cl { color:#111 }
/* LineLink */ .chroma .lnlinks { outline:none;text-decoration:none;color:inherit }
/* LineTableTD */ .chroma .lntd { vertical-align:top;padding:0;margin:0;border:0; }
/* LineTable */ .chroma .lntable { border-spacing:0;padding:0;margin:0;border:0; }
/* LineHighlight */ .chroma .hl { background-color:#e1e1e1 }
/* LineNumbersTable */ .chroma .lnt { white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f }
/* LineNumbers */ .chroma .ln { white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f }
/* Line */ .chroma .line { display:flex; }
/* Keyword */ .chroma .k { color:#00a8c8 }
/* KeywordConstant */ .chroma .kc { color:#00a8c8 }
/* KeywordDeclaration */ .chroma .kd { color:#00a8c8 }
/* KeywordNamespace */ .chroma .kn { color:#f92672 }
/* KeywordPseudo */ .chroma .kp { color:#00a8c8 }
/* KeywordReserved */ .chroma .kr { color:#00a8c8 }
/* KeywordType */ .chroma .kt { color:#00a8c8 }
/* Name */ .chroma .n { color:#383a42 }
/* NameAttribute */ .chroma .na { color:#75af00 }
/* NameBuiltin */ .chroma .nb { color:#111 }
/* NameBuiltinPseudo */ .chroma .bp { color:#111 }
/* NameClass */ .chroma .nc { color:#75af00 }
/* NameConstant */ .chroma .no { color:#00a8c8 }
/* NameDecorator */ .chroma .nd { color:#75af00 }
/* NameEntity */ .chroma .ni { color:#111 }
/* NameException */ .chroma .ne { color:#75af00 }
/* NameFunction */ .chroma .nf { color:#75af00 }
/* NameFunctionMagic */ .chroma .fm { color:#111 }
/* NameLabel */ .chroma .nl { color:#111 }
/* NameNamespace */ .chroma .nn { color:#111 }
/* NameOther */ .chroma .nx { color:#75af00 }
/* NameProperty */ .chroma .py { color:#111 }
/* NameTag */ .chroma .nt { color:#f92672 }
/* NameVariable */ .chroma .nv { color:#111 }
/* NameVariableClass */ .chroma .vc { color:#111 }
/* NameVariableGlobal */ .chroma .vg { color:#111 }
/* NameVariableInstance */ .chroma .vi { color:#111 }
/* NameVariableMagic */ .chroma .vm { color:#111 }
/* Literal */ .chroma .l { color:#ae81ff }
/* LiteralDate */ .chroma .ld { color:#d88200 }
/* LiteralString */ .chroma .s { color:#d88200 }
/* LiteralStringAffix */ .chroma .sa { color:#d88200 }
/* LiteralStringBacktick */ .chroma .sb { color:#d88200 }
/* LiteralStringChar */ .chroma .sc { color:#d88200 }
/* LiteralStringDelimiter */ .chroma .dl { color:#d88200 }
/* LiteralStringDoc */ .chroma .sd { color:#d88200 }
/* LiteralStringDouble */ .chroma .s2 { color:#d88200 }
/* LiteralStringEscape */ .chroma .se { color:#8045ff }
/* LiteralStringHeredoc */ .chroma .sh { color:#d88200 }
/* LiteralStringInterpol */ .chroma .si { color:#d88200 }
/* LiteralStringOther */ .chroma .sx { color:#d88200 }
/* LiteralStringRegex */ .chroma .sr { color:#d88200 }
/* LiteralStringSingle */ .chroma .s1 { color:#d88200 }
/* LiteralStringSymbol */ .chroma .ss { color:#d88200 }
/* LiteralNumber */ .chroma .m { color:#ae81ff }
/* LiteralNumberBin */ .chroma .mb { color:#ae81ff }
/* LiteralNumberFloat */ .chroma .mf { color:#ae81ff }
/* LiteralNumberHex */ .chroma .mh { color:#ae81ff }
/* LiteralNumberInteger */ .chroma .mi { color:#ae81ff }
/* LiteralNumberIntegerLong */ .chroma .il { color:#ae81ff }
/* LiteralNumberOct */ .chroma .mo { color:#ae81ff }
/* Operator */ .chroma .o { color:#f92672 }
/* OperatorWord */ .chroma .ow { color:#f92672 }
/* Punctuation */ .chroma .p { color:#111 }
/* Comment */ .chroma .c { color:#a0a1a7 }
/* CommentHashbang */ .chroma .ch { color:#a0a1a7 }
/* CommentMultiline */ .chroma .cm { color:#a0a1a7 }
/* CommentSingle */ .chroma .c1 { color:#a0a1a7 }
/* CommentSpecial */ .chroma .cs { color:#a0a1a7 }
/* CommentPreproc */ .chroma .cp { color:#a0a1a7 }
/* CommentPreprocFile */ .chroma .cpf { color:#a0a1a7 }
/* Generic */ .chroma .g {  }
/* GenericDeleted */ .chroma .gd {  }
/* GenericEmph */ .chroma .ge { font-style:italic }
/* GenericError */ .chroma .gr {  }
/* GenericHeading */ .chroma .gh {  }
/* GenericInserted */ .chroma .gi {  }
/* GenericOutput */ .chroma .go {  }
/* GenericPrompt */ .chroma .gp {  }
/* GenericStrong */ .chroma .gs { font-weight:bold }
/* GenericSubheading */ .chroma .gu {  }
/* GenericTraceback */ .chroma .gt {  }
/* GenericUnderline */ .chroma .gl {  }
/* TextWhitespace */ .chroma .w {  }

2.在 Hugo 项目根目录下的 assets/css/extended/chroma-dark.css,新建/追加:

/* Background */ .bg { color:#f8f8f2;background-color:#272822; }
/* PreWrapper */ .dark .chroma { color:#f8f8f2;background-color:#272822; }
/* Other */ .dark .chroma .x {  }
/* Error */ .dark .chroma .err { color:#e769ac; }
/* CodeLine */ .dark .chroma .cl { color:#cdcdcd }
/* LineLink */ .dark .chroma .lnlinks { outline:none;text-decoration:none;color:inherit }
/* LineTableTD */ .dark .chroma .lntd { vertical-align:top;padding:0;margin:0;border:0; }
/* LineTable */ .dark .chroma .lntable { border-spacing:0;padding:0;margin:0;border:0; }
/* LineHighlight */ .dark .chroma .hl { background-color:#3c3d38 }
/* LineNumbersTable */ .dark .chroma .lnt { white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f }
/* LineNumbers */ .dark .chroma .ln { white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f }
/* Line */ .dark .chroma .line { display:flex; }
/* Keyword */ .dark .chroma .k { color:#66d9ef }
/* KeywordConstant */ .dark .chroma .kc { color:#66d9ef }
/* KeywordDeclaration */ .dark .chroma .kd { color:#66d9ef }
/* KeywordNamespace */ .dark .chroma .kn { color:#f92672 }
/* KeywordPseudo */ .dark .chroma .kp { color:#66d9ef }
/* KeywordReserved */ .dark .chroma .kr { color:#66d9ef }
/* KeywordType */ .dark .chroma .kt { color:#66d9ef }
/* Name */ .dark .chroma .n { color:#cdcdcd }
/* NameAttribute */ .dark .chroma .na { color:#a6e22e }
/* NameBuiltin */ .dark .chroma .nb { color:#cdcdcd }
/* NameBuiltinPseudo */ .dark .chroma .bp { color:#cdcdcd }
/* NameClass */ .dark .chroma .nc { color:#a6e22e }
/* NameConstant */ .dark .chroma .no { color:#66d9ef }
/* NameDecorator */ .dark .chroma .nd { color:#a6e22e }
/* NameEntity */ .dark .chroma .ni { color:#cdcdcd }
/* NameException */ .dark .chroma .ne { color:#a6e22e }
/* NameFunction */ .dark .chroma .nf { color:#a6e22e }
/* NameFunctionMagic */ .dark .chroma .fm { color:#cdcdcd }
/* NameLabel */ .dark .chroma .nl { color:#cdcdcd }
/* NameNamespace */ .dark .chroma .nn { color:#8282f2 }
/* NameOther */ .dark .chroma .nx { color:#a6e22e }
/* NameProperty */ .dark .chroma .py { color:#cdcdcd }
/* NameTag */ .dark .chroma .nt { color:#f92672 }
/* NameVariable */ .dark .chroma .nv { color:#cdcdcd }
/* NameVariableClass */ .dark .chroma .vc { color:#cdcdcd }
/* NameVariableGlobal */ .dark .chroma .vg { color:#cdcdcd }
/* NameVariableInstance */ .dark .chroma .vi { color:#cdcdcd }
/* NameVariableMagic */ .dark .chroma .vm { color:#cdcdcd }
/* Literal */ .dark .chroma .l { color:#ae81ff }
/* LiteralDate */ .dark .chroma .ld { color:#e6db74 }
/* LiteralString */ .dark .chroma .s { color:#e6db74 }
/* LiteralStringAffix */ .dark .chroma .sa { color:#e6db74 }
/* LiteralStringBacktick */ .dark .chroma .sb { color:#e6db74 }
/* LiteralStringChar */ .dark .chroma .sc { color:#e6db74 }
/* LiteralStringDelimiter */ .dark .chroma .dl { color:#e6db74 }
/* LiteralStringDoc */ .dark .chroma .sd { color:#e6db74 }
/* LiteralStringDouble */ .dark .chroma .s2 { color:#e6db74 }
/* LiteralStringEscape */ .dark .chroma .se { color:#ae81ff }
/* LiteralStringHeredoc */ .dark .chroma .sh { color:#e6db74 }
/* LiteralStringInterpol */ .dark .chroma .si { color:#e6db74 }
/* LiteralStringOther */ .dark .chroma .sx { color:#e6db74 }
/* LiteralStringRegex */ .dark .chroma .sr { color:#e6db74 }
/* LiteralStringSingle */ .dark .chroma .s1 { color:#e6db74 }
/* LiteralStringSymbol */ .dark .chroma .ss { color:#e6db74 }
/* LiteralNumber */ .dark .chroma .m { color:#ae81ff }
/* LiteralNumberBin */ .dark .chroma .mb { color:#ae81ff }
/* LiteralNumberFloat */ .dark .chroma .mf { color:#ae81ff }
/* LiteralNumberHex */ .dark .chroma .mh { color:#ae81ff }
/* LiteralNumberInteger */ .dark .chroma .mi { color:#ae81ff }
/* LiteralNumberIntegerLong */ .dark .chroma .il { color:#ae81ff }
/* LiteralNumberOct */ .dark .chroma .mo { color:#ae81ff }
/* Operator */ .dark .chroma .o { color:#f92672 }
/* OperatorWord */ .dark .chroma .ow { color:#f92672 }
/* Punctuation */ .dark .chroma .p { color:#cdcdcd }
/* Comment */ .dark .chroma .c { color:#939fd4cf }
/* CommentHashbang */ .dark .chroma .ch { color:#939fd4cf }
/* CommentMultiline */ .dark .chroma .cm { color:#939fd4cf }
/* CommentSingle */ .dark .chroma .c1 { color:#939fd4cf }
/* CommentSpecial */ .dark .chroma .cs { color:#939fd4cf }
/* CommentPreproc */ .dark .chroma .cp { color:#939fd4cf }
/* CommentPreprocFile */ .dark .chroma .cpf { color:#939fd4cf }
/* Generic */ .dark .chroma .g {  }
/* GenericDeleted */ .dark .chroma .gd { color:#f92672 }
/* GenericEmph */ .dark .chroma .ge { font-style:italic }
/* GenericError */ .dark .chroma .gr {  }
/* GenericHeading */ .dark .chroma .gh {  }
/* GenericInserted */ .dark .chroma .gi { color:#a6e22e }
/* GenericOutput */ .dark .chroma .go {  }
/* GenericPrompt */ .dark .chroma .gp {  }
/* GenericStrong */ .dark .chroma .gs { font-weight:bold }
/* GenericSubheading */ .dark .chroma .gu { color:#939fd4cf }
/* GenericTraceback */ .dark .chroma .gt {  }
/* GenericUnderline */ .dark .chroma .gl {  }
/* TextWhitespace */ .dark .chroma .w {  }

3.在 Hugo 项目根目录下的 assets/css/extended/blank.css,新建/追加:

/* 修改文章代码块白天的背景色 */
:root {
    --hljs-bg: rgb(247, 247, 247);
}

4.修改 Hugo 项目根目录下 config.yml 中的目录配置,禁用 highlight.js,启用 chroma。

params:
  assets:
    disableHLJS: true
markup:
  highlight:
    noClasses: false

魔改PaperMod主题和博客改动-20240814120958605

这样就舒坦多了嘛

参考 WIP: Add auto light/dark syntax highlight theme switch with chroma by ataias · Pull Request #143 · adityatelange/hugo-PaperMod · GitHub

八、添加图片灯箱效果

文章里常常会附上图片,没法点击放大查看真的很难受呗。

简单检索,决定使用 Fancybox,看到 24 年还有教程里用的是 10 年的 jQuery 实现的 Fancybox,也是泪目了=。=

1.在 Hugo 项目根目录下的 layouts/partials/extend_footer.html,新建/追加:

<!-- 给图片添加Fancybox灯箱 -->
{{ if not .Page.IsHome }}
{{ $script := resources.Get "js/fancybox.umd.min.js"}}
<script src={{ $script.Permalink }}></script>

{{ $styles := resources.Get "css/fancybox.min.css"}}
<link rel="stylesheet" href="{{ $styles.Permalink }}">

<script>
    Fancybox.bind("[data-fancybox]", {
        // Your custom options
    });
</script>
{{ end }}

这里你当然也可以使用 CDN 引用,但是 CDNJS 国内体验不咋地,所以我就用本地引用了。

2.将上面 CDN 中的 fancybox.umd.min.jsfancybox.min.css 内容复制下来,分别新建保存到 Hugo 项目根目录的 assets/js/fancybox.umd.min.jsassets/css/fancybox.min.css 文件中。

3.在 Hugo 项目根目录下的 layouts/default/_markup/render-image.html,新建/追加:

<!-- 给图片添加Fancybox灯箱 -->
<div class="post-img-view">
    <a data-fancybox="gallery" href="{{ .Destination | safeURL }}" data-caption="{{ .Text }}">
        <img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" {{ with .Title}} title="{{ . }}" {{ end }} />
    </a>
</div>

参考 Hugo Fancybox实现图片灯箱效果

九、其他改动

  1. 添加了 Archive 归档页面,时间轴展示还不错。
  2. 启用了 Cloudflare DNS 代理,来保持内地网站顺利访问,Vercel 有时候内地会访问不了,虽然 Vercel 速度比较块,但还是访问稳定第一。
  3. 升级 Twikko 到 v1.6.39,之前老版本用的还是最近被投毒的 CDN,我就说评论组件咋加载不出来了,原来是 CDN 被 AdGuard 屏蔽了。

十、小尾巴

这样一折腾之前几个痛点也是被我解决了,那么,代价是什么呢......

哈哈,代价就是谷歌的 PageSpeed Insights 评分腰斩,从 100&99,变成了现在的 59&89。不过访问速度倒没加多少,依旧优秀(哼哼叉会腰)。

此外思想上不再局限于写技术博客了,之后会写点和技术无关的,生活,摄影啥的,不比技术有意思嘛,嘿嘿。