此篇博客介绍我的博客的修改内容和方法。我的主题为 hugo-PaperMod。我修改前都将博客内的资源文件夹 (assets, i18n, lay) 复制到了项目根目录中,这样以后更新主题也不会导致修改消失。。

石蒜小组件

来自与 Github。项目地址为:https://github.com/dsrkafuu/sakana-widget。具体更改为在 /layouts/partials/extend_footer.html 中加入如下代码:

<!--  石蒜组件 -->
<style>
    html #sakana-widget{
        position: fixed;
        right: 50px;
        bottom: 0;
      
        transform-origin: 100% 100%; /* 从右下开始变换 */
}
</style>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/sakana-widget@2.4.1/lib/sakana.min.css"
/>
<div id="sakana-widget", style="z-index:999"></div>
<script>
function initSakanaWidget() {
    new SakanaWidget().mount('#sakana-widget');
}
</script>
<script
async
onload="initSakanaWidget()"
src="https://cdn.jsdelivr.net/npm/sakana-widget@2.4.1/lib/sakana.min.js"
></script>

重新编译后即可拥有可爱石蒜小组件。sakana

High 一下

有两种 High 一下的代码实现:

javascript:(function(){function c(){var e=document.createElement("link");e.setAttribute("type","text/css");e.setAttribute("rel","stylesheet");e.setAttribute("href",f);e.setAttribute("class",l);document.body.appendChild(e)}function h(){var e=document.getElementsByClassName(l);for(var t=0;t<e.length;t++){document.body.removeChild(e[t])}}function p(){var e=document.createElement("div");e.setAttribute("class",a);document.body.appendChild(e);setTimeout(function(){document.body.removeChild(e)},100)}function d(e){return{height:e.offsetHeight,width:e.offsetWidth}}function v(i){var s=d(i);return s.height>e&&s.height<n&&s.width>t&&s.width<r}function m(e){var t=e;var n=0;while(!!t){n+=t.offsetTop;t=t.offsetParent}return n}function g(){var e=document.documentElement;if(!!window.innerWidth){return window.innerHeight}else if(e&&!isNaN(e.clientHeight)){return e.clientHeight}return 0}function y(){if(window.pageYOffset){return window.pageYOffset}return Math.max(document.documentElement.scrollTop,document.body.scrollTop)}function E(e){var t=m(e);return t>=w&&t<=b+w}function S(){var e=document.createElement("audio");e.setAttribute("class",l);e.src=i;e.loop=false;e.addEventListener("canplay",function(){setTimeout(function(){x(k)},500);setTimeout(function(){N();p();for(var e=0;e<O.length;e++){T(O[e])}},15500)},true);e.addEventListener("ended",function(){N();h()},true);e.innerHTML=" <p>If you are reading this, it is because your browser does not support the audio element. We recommend that you get a new browser.</p> <p>";document.body.appendChild(e);e.play()}function x(e){e.className+=" "+s+" "+o}function T(e){e.className+=" "+s+" "+u[Math.floor(Math.random()*u.length)]}function N(){var e=document.getElementsByClassName(s);var t=new RegExp("\\b"+s+"\\b");for(var n=0;n<e.length;){e[n].className=e[n].className.replace(t,"")}}var e=30;var t=30;var n=350;var r=350;var i="//s3.amazonaws.com/moovweb-marketing/playground/harlem-shake.mp3";var s="mw-harlem_shake_me";var o="im_first";var u=["im_drunk","im_baked","im_trippin","im_blown"];var a="mw-strobe_light";var f="//s3.amazonaws.com/moovweb-marketing/playground/harlem-shake-style.css";var l="mw_added_css";var b=g();var w=y();var C=document.getElementsByTagName("*");var k=null;for(var L=0;L<C.length;L++){var A=C[L];if(v(A)){if(E(A)){k=A;break}}}if(A===null){console.warn("Could not find a node of the right size. Please try a different page.");return}c();S();var O=[];for(var L=0;L<C.length;L++){var A=C[L];if(v(A)){O.push(A)}}})()
  • 第二种:来自于 Github 的 代码 :
javascript:(function(){function h(){var e=document.createElement("link");e.setAttribute("type","text/css");e.setAttribute("rel","stylesheet");e.setAttribute("href",l);e.setAttribute("class",c);document.body.appendChild(e)}function p(){var e=document.getElementsByClassName(c);for(var t=0;t<e.length;t++){document.body.removeChild(e[t])}}function d(){var e=document.createElement("div");e.setAttribute("class",f);document.body.appendChild(e);setTimeout(function(){document.body.removeChild(e)},100)}function v(e){return{height:e.offsetHeight,width:e.offsetWidth}}function m(i){var s=v(i);return s.height>e&&s.height<n&&s.width>t&&s.width<r}function g(e){var t=e;var n=0;while(!!t){n+=t.offsetTop;t=t.offsetParent}return n}function y(){var e=document.documentElement;if(!!window.innerWidth){return window.innerHeight}else if(e&&!isNaN(e.clientHeight)){return e.clientHeight}return 0}function b(){if(window.pageYOffset){return window.pageYOffset}return Math.max(document.documentElement.scrollTop,document.body.scrollTop)}function S(e){var t=g(e);return t>=E&&t<=w+E}function x(){var e=document.createElement("audio");e.setAttribute("class",c);e.src=i;e.loop=false;var t=false,n=false,r=false;e.addEventListener("timeupdate",function(){var i=e.currentTime,s=D,o=s.length,u;if(i>=.5&&!t){t=true;T(_)}if(i>=15.5&&!n){n=true;k();d();for(u=0;u<o;u++){N(s[u])}}if(e.currentTime>=28.4&&!r){r=true;C()}},true);e.addEventListener("ended",function(){k();p()},true);e.innerHTML="<p>If you are reading this, it is because your browser does not support the audio element. We recommend that you get a new browser.</p>";document.body.appendChild(e);e.play()}function T(e){e.className+=" "+s+" "+u}function N(e){e.className+=" "+s+" "+a[Math.floor(Math.random()*a.length)]}function C(){var e=document.getElementsByClassName(s);for(var t=0;t<e.length;){e[t].className=e[t].className.replace(s,o)}s=o}function k(){var e=document.getElementsByClassName(s);var t=new RegExp("\\b"+s+"\\b");for(var n=0;n<e.length;){e[n].className=e[n].className.replace(t,"")}}var e=30;var t=30;var n=350;var r=350;var i="//s3.amazonaws.com/moovweb-marketing/playground/harlem-shake.ogg";var s="mw-harlem_shake_me";var o="mw-harlem_shake_slow";var u="im_first";var a=["im_drunk","im_baked","im_trippin","im_blown"];var f="mw-strobe_light";var l="//s3.amazonaws.com/moovweb-marketing/playground/harlem-shake-style.css";var c="mw_added_css";var w=y();var E=b();var L=document.getElementsByTagName("*"),A=L.length,O,M;var _=null;for(O=0;O<A;O++){M=L[O];if(m(M)){if(S(M)){_=M;break}}}if(M===null){console.warn("Could not find a node of the right size. Please try a different page.");return}h();x();var D=[];for(O=0;O<A;O++){M=L[O];if(m(M)){D.push(M)}}})()

以上两种差不多,我个人用的是第二种。具体用法为在 /layouts/partials/extend_head.html 中加入如下代码:

<!--  High 一下 --> 
<style>
    html .pull-right{
        position: absolute;
        right: 0;
        top: 70px;
      
        transform-origin: 100% 100%; /* 从右下开始变换 */
    }
</style>

<div class="pull-right", style="z-index:999">
<a title="把这个链接拖到你的Chrome收藏夹工具栏中" href='javascript:(function(){function h(){var e=document.createElement("link");e.setAttribute("type","text/css");e.setAttribute("rel","stylesheet");e.setAttribute("href",l);e.setAttribute("class",c);document.body.appendChild(e)}function p(){var e=document.getElementsByClassName(c);for(var t=0;t<e.length;t++){document.body.removeChild(e[t])}}function d(){var e=document.createElement("div");e.setAttribute("class",f);document.body.appendChild(e);setTimeout(function(){document.body.removeChild(e)},100)}function v(e){return{height:e.offsetHeight,width:e.offsetWidth}}function m(i){var s=v(i);return s.height>e&&s.height<n&&s.width>t&&s.width<r}function g(e){var t=e;var n=0;while(!!t){n+=t.offsetTop;t=t.offsetParent}return n}function y(){var e=document.documentElement;if(!!window.innerWidth){return window.innerHeight}else if(e&&!isNaN(e.clientHeight)){return e.clientHeight}return 0}function b(){if(window.pageYOffset){return window.pageYOffset}return Math.max(document.documentElement.scrollTop,document.body.scrollTop)}function S(e){var t=g(e);return t>=E&&t<=w+E}function x(){var e=document.createElement("audio");e.setAttribute("class",c);e.src=i;e.loop=false;var t=false,n=false,r=false;e.addEventListener("timeupdate",function(){var i=e.currentTime,s=D,o=s.length,u;if(i>=.5&&!t){t=true;T(_)}if(i>=15.5&&!n){n=true;k();d();for(u=0;u<o;u++){N(s[u])}}if(e.currentTime>=28.4&&!r){r=true;C()}},true);e.addEventListener("ended",function(){k();p()},true);e.innerHTML="<p>If you are reading this, it is because your browser does not support the audio element. We recommend that you get a new browser.</p>";document.body.appendChild(e);e.play()}function T(e){e.className+=" "+s+" "+u}function N(e){e.className+=" "+s+" "+a[Math.floor(Math.random()*a.length)]}function C(){var e=document.getElementsByClassName(s);for(var t=0;t<e.length;){e[t].className=e[t].className.replace(s,o)}s=o}function k(){var e=document.getElementsByClassName(s);var t=new RegExp("\\b"+s+"\\b");for(var n=0;n<e.length;){e[n].className=e[n].className.replace(t,"")}}var e=30;var t=30;var n=350;var r=350;var i="//s3.amazonaws.com/moovweb-marketing/playground/harlem-shake.ogg";var s="mw-harlem_shake_me";var o="mw-harlem_shake_slow";var u="im_first";var a=["im_drunk","im_baked","im_trippin","im_blown"];var f="mw-strobe_light";var l="//s3.amazonaws.com/moovweb-marketing/playground/harlem-shake-style.css";var c="mw_added_css";var w=y();var E=b();var L=document.getElementsByTagName("*"),A=L.length,O,M;var _=null;for(O=0;O<A;O++){M=L[O];if(m(M)){if(S(M)){_=M;break}}}if(M===null){console.warn("Could not find a node of the right size. Please try a different page.");return}h();x();var D=[];for(O=0;O<A;O++){M=L[O];if(m(M)){D.push(M)}}})()'>High 一下!</a>
</div>

其中的 href= 的内容替换为上述两种的其中一种即可。

2024-04-03 更新

原来脚本所请求的存储在亚马逊云服务上的音频文件和 css 文件现在获取不到了,导致这个脚本执行报错。可以去 web archive 上找到这两个链接的存档,替换即可。替换后的代码为:

<!--  High 一下 --> 
<style>
    html .pull-right{
        position: absolute;
        right: 0;
        top: 70px;
    
        transform-origin: 100% 100%; /* 从右下开始变换 */
    }
</style>

<div class="pull-right", style="z-index:999">
<a title="把这个链接拖到你的Chrome收藏夹工具栏中" href="
javascript:
	(function () {
		function h() {
			var e = document.createElement('link');
			e.setAttribute('type', 'text/css');
			e.setAttribute('rel', 'stylesheet');
			e.setAttribute('href', l);
			e.setAttribute('class', c);
			document.body.appendChild(e);
		}
		function p() {
			var e = document.getElementsByClassName(c);
			for (var t = 0; t < e.length; t++) {
				document.body.removeChild(e[t]);
			}
		}
		function d() {
			var e = document.createElement('div');
			e.setAttribute('class', f);
			document.body.appendChild(e);
			setTimeout(function () {
				document.body.removeChild(e);
			}, 100);
		}
		function v(e) {
			return {
				height: e.offsetHeight,
				width: e.offsetWidth
			};
		}
		function m(i) {
			var s = v(i);
			return s.height > e && s.height < n && s.width > t && s.width < r;
		}
		function g(e) {
			var t = e;
			var n = 0;
			while (!!t) {
				n += t.offsetTop;
				t = t.offsetParent;
			}
			return n;
		}
		function y() {
			var e = document.documentElement;
			if (!!window.innerWidth) {
				return window.innerHeight;
			} else if (e && !isNaN(e.clientHeight)) {
				return e.clientHeight;
			}
			return 0;
		}
		function b() {
			if (window.pageYOffset) {
				return window.pageYOffset;
			}
			return Math.max(document.documentElement.scrollTop, document.body.scrollTop);
		}
		function S(e) {
			var t = g(e);
			return t >= E && t <= w + E;
		}
		function x() {
			var e = document.createElement('audio');
			e.setAttribute('class', c);
			e.src = i;
			e.loop = false;
			var t = false, n = false, r = false;
			e.addEventListener('timeupdate', function () {
				var i = e.currentTime, s = D, o = s.length, u;
				if (i >= 0.5 && !t) {
					t = true;
					T(_);
				}
				if (i >= 15.5 && !n) {
					n = true;
					k();
					d();
					for (u = 0; u < o; u++) {
						N(s[u]);
					}
				}
				if (e.currentTime >= 28.4 && !r) {
					r = true;
					C();
				}
			}, true);
			e.addEventListener('ended', function () {
				k();
				p();
			}, true);
			e.innerHTML = '<p>If you are reading this, it is because your browser does not support the audio element. We recommend that you get a new browser.</p>';
			document.body.appendChild(e);
			e.play();
		}
		function T(e) {
			e.className += ' ' + s + ' ' + u;
		}
		function N(e) {
			e.className += ' ' + s + ' ' + a[Math.floor(Math.random() * a.length)];
		}
		function C() {
			var e = document.getElementsByClassName(s);
			for (var t = 0; t < e.length;) {
				e[t].className = e[t].className.replace(s, o);
			}
			s = o;
		}
		function k() {
			var e = document.getElementsByClassName(s);
			var t = new RegExp('\\b' + s + '\\b');
			for (var n = 0; n < e.length;) {
				e[n].className = e[n].className.replace(t, '');
			}
		}
		var e = 30;
		var t = 30;
		var n = 350;
		var r = 350;
		var i = '//web.archive.org/web/20240301073522/s3.amazonaws.com/moovweb-marketing/playground/harlem-shake.mp3';
		var s = 'mw-harlem_shake_me';
		var o = 'mw-harlem_shake_slow';
		var u = 'im_first';
		var a = [
			'im_drunk',
			'im_baked',
			'im_trippin',
			'im_blown'
		];
		var f = 'mw-strobe_light';
		var l = '//web.archive.org/web/20230212043533/s3.amazonaws.com/moovweb-marketing/playground/harlem-shake-style.css';
		var c = 'mw_added_css';
		var w = y();
		var E = b();
		var L = document.getElementsByTagName('*'), A = L.length, O, M;
		var _ = null;
		for (O = 0; O < A; O++) {
			M = L[O];
			if (m(M)) {
				if (S(M)) {
					_ = M;
					break;
				}
			}
		}
		if (M === null) {
			console.warn('Could not find a node of the right size. Please try a different page.');
			return;
		}
		h();
		x();
		var D = [];
		for (O = 0; O < A; O++) {
			M = L[O];
			if (m(M)) {
				D.push(M);
			}
		}
	}());
">High 一下!</a>
</div>

修改目录位置到文章页左边

根据 sulvblog 的方法来改。

修改 toc.html

先修改 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 }}

调用

layouts/_default/single.html 文件中默认有 toc.html 的调用,如果未更改的话不用管,更改的话请调用:

{{- if (.Param "ShowToc") }}
{{- partial "toc.html" . }}
{{- end }}

修改 css

修改 css/extended/blank.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;

    /*目录显示高度*/
    max-height: 83vh;
    overflow-y: auto;
}

.toc .inner::-webkit-scrollbar-thumb {  /*滚动条*/
    background: var(--border);
    border: 7px solid var(--theme);
    border-radius: var(--radius);
}

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

重新编译后即可看到目录到了左边。

修改主题内容宽度

修改 ·assets/css/core/theme-vars.css 文件的 :root 节点中的 --main-width 我设置的是 1024px

修改代码块

修改渲染方式

放弃主题默认的 Highlight.js,改为 Hugo 默认的 chroma 方式渲染。根据 官方说明 来改。我用的 style 为 github-dark

设置代码块最大高度

assets/css/common/post-single.css 文件中找到 .post-content code 增加 max-height: 40em; 。目前设置好最大高度后会与 lineNos: true 设置冲突,会显示两个滑动条 :( ,所以就先不开它。

修改文章列表显示的图片位置

默认显示的图片在摘要上方而且很大,一页只能显示几个,感觉体验不是很好,所以将它改为在摘要右方显示。我很喜欢 CoolShell 的文章页的显示方法,准备改成差不多样子的。

修改 list.html

文件为 layouts/_default/list.html 。默认的图片显示代码为:

{{- $isHidden := (site.Params.cover.hidden | default site.Params.cover.hiddenInList) }}
{{- partial "cover.html" (dict "cxt" . "IsHome" true "isHidden" $isHidden) }}

位于 <header class="entry-header"> 的上方。将其移动到 <div class="entry-content"> 中并替换默认的 Summary 处理方式,如下所示:

<div class="entry-content">
    {{- $isHidden := (site.Params.cover.hidden | default site.Params.cover.hiddenInList) }}
    {{- partial "cover.html" (dict "cxt" . "IsHome" true "isHidden" $isHidden) }}
    {{ .Summary | replaceRE "\n" "<br>" | safeHTML }}{{ if .Truncated }}...{{ end }}
</div>

修改 cover.html

文件为 layouts/partials/cover.html 。将 所有 <img 块都加上 align="right" 。完整如下所示:

{{- with .cxt}} {{/* Apply proper context from dict */}}
{{- if (and .Params.cover.image (not $.isHidden)) }}
{{- $alt := (.Params.cover.alt | default .Params.cover.caption | plainify) }}
<figure class="entry-cover">
    {{- $responsiveImages := (.Params.cover.responsiveImages | default site.Params.cover.responsiveImages) | default true }}
    {{- $addLink := (and site.Params.cover.linkFullImages (not $.IsHome)) }}
    {{- $pageBundleCover     := (.Resources.ByType "image").GetMatch (printf "*%s*" (.Params.cover.image)) }}
    {{- $globalResourcesCover := (resources.ByType "image").GetMatch (printf "*%s*" (.Params.cover.image)) }}
    {{- $cover := (or $pageBundleCover $globalResourcesCover)}}
    {{- if $cover -}}{{/* i.e it is present in page bundle */}}
        {{- if $addLink }}<a href="{{ (path.Join .RelPermalink .Params.cover.image) | absURL }}" target="_blank"
            rel="noopener noreferrer">{{ end -}}
        {{- $sizes := (slice "360" "480" "720" "1080" "1500") }}
        {{- $processableFormats := (slice "jpg" "jpeg" "png" "tif" "bmp" "gif") -}}
        {{- if hugo.IsExtended -}}
            {{- $processableFormats = $processableFormats | append "webp" -}}
        {{- end -}}
        {{- $prod := (hugo.IsProduction | or (eq site.Params.env "production")) }}
        {{- if (and (in $processableFormats $cover.MediaType.SubType) ($responsiveImages) (eq $prod true)) }}
        <img loading="lazy" align="right" srcset="{{- range $size := $sizes -}}
                        {{- if (ge $cover.Width $size) -}}
                        {{ printf "%s %s" (($cover.Resize (printf "%sx" $size)).Permalink) (printf "%sw ," $size) -}}
                        {{ end }}
                    {{- end -}}{{$cover.Permalink }} {{printf "%dw" ($cover.Width)}}" 
            sizes="(min-width: 768px) 720px, 100vw" src="{{ $cover.Permalink }}" alt="{{ $alt }}" 
            width="{{ $cover.Width }}" height="{{ $cover.Height }}">
        {{- else }}{{/* Unprocessable image or responsive images disabled */}}
        <img loading="lazy" align="right" src="{{ (path.Join .RelPermalink .Params.cover.image) | absURL }}" alt="{{ $alt }}">
        {{- end }}
    {{- else }}{{/* For absolute urls and external links, no img processing here */}}
        {{- if $addLink }}<a href="{{ (.Params.cover.image) | absURL }}" target="_blank"
            rel="noopener noreferrer">{{ end -}}
            <img loading="lazy" align="right" src="{{ (.Params.cover.image) | absURL }}" alt="{{ $alt }}">
    {{- end }}
    {{- if $addLink }}</a>{{ end -}}
    {{/*  Display Caption  */}}
    {{- if not $.IsHome }}
        {{ with .Params.cover.caption }}<p>{{ . | markdownify }}</p>{{- end }}
    {{- end }}
</figure>
{{- end }}{{/* End image */}}
{{- end -}}{{/* End context */ -}}

增加 css

在文件 assets/css/extended/blank.css 中增加以下代码:

.entry-cover {
    float:right;
    width: 20%;
    margin-left: 20px;
}

.entry-content {
    margin: 20px 0;
    color: var(--secondary);
    font-size: 14px;
    line-height: 1.6;
    overflow: hidden;
    display: block;
}

这样做完的效果就是文章列表页的摘要可以自由显示文字和图片,默认的 cover 在文字右边,文字会环绕图片显示。

标签页词云效果

根据 Sulv's Blog 的方法来改。

修改 terms.html

layouts/_default/terms.html 中的 <ul class="terms-tags"> 代码块替换为:

<ul class="terms-tags">
    {{- $type := .Type }}
    {{- range $key, $value := .Data.Terms.Alphabetical }}
    {{- $name := .Name }}
    {{- $count := .Count }}
    {{- with $.Site.GetPage (printf "/%s/%s" $type $name) }}
    <li>
        {{ $largestFontSize := 1.5 }}
        {{ $smallestFontSize := 1 }}
        {{ $fontSpread := sub $largestFontSize $smallestFontSize }}
        {{ $max := add (len (index $.Site.Taxonomies.tags.ByCount 0).Pages) 1 }}
        {{ $min := len (index $.Site.Taxonomies.tags.ByCount.Reverse 0).Pages }}
        {{ $spread := sub $max $min }}
        {{ $fontStep := div $fontSpread $spread }}
        {{ $weigth := div (sub (math.Log $count) (math.Log $min)) (sub (math.Log $max) (math.Log $min)) }}
        {{ $currentFontSize := (add $smallestFontSize (mul (sub $largestFontSize $smallestFontSize) $weigth)) }}
        <a href="{{ .Permalink }}" style="font-size: {{ $currentFontSize }}rem; font-weight: {{ mul $currentFontSize 200 }};">
            {{ .Name }} <sup><strong><sup>{{ $count }}</sup></strong></sup>
        </a>
    </li>
    {{- end }}
    {{- end }}
</ul>

增加 css

assets/css/extended/blank.css 中增加如下代码:

/*标签*/
.terms-tags {
    text-align: center;
}

.terms-tags a:hover {
    background: none;
    -moz-transform: scale(1.2);
    -ms-transform: scale(1.2);
    -o-transform: scale(1.2);
    transform: scale(1.3);
}

.terms-tags a {
    border-radius: 30px;
    background: none;
    transition: transform 0.5s;
}

.dark .terms-tags a {
    background: none;
}

.dark .terms-tags a:hover {
    background: none;
    -moz-transform: scale(1.2);
    -ms-transform: scale(1.2);
    -o-transform: scale(1.2);
    transform: scale(1.3);
}

.terms-tags li {
    margin: 5px;
}

创建关于页

创建 about.md 文件

使用命令 hugo new content about.md 创建关于页。将 front matter 替换为如下内容:

title: '关于我'  # 显示的标题
layout: "about"  # 使用的 html 模板
# url: "/about"
description: "兴趣使然的程序员" # 头像下方的简短介绍
comments: true  # 是否开启评论
avatar: "/images/avatar.gif" # 头像

创建 html 模板

创建 layouts/_default/about.html 文件,填入以下代码:

{{ define "main" }}

<header class="page-header">
  <h1>{{ .Title }}</h1>
</header>

<div class="about-container">
  <div class="about-avatar">
    <img src="{{ .Params.avatar }}" alt="头像" />
  </div>
  <div class="about-description">
    {{ .Params.description }}
  </div>
</div>
<div class="post-content">
  {{ .Content }}
</div>
{{- if (.Param "comments") }}
{{- partial "comments.html" . }}
{{- end }}
{{ end }}

增加 css

assets/css/extended/custom.css 中增加以下代码:

/* about page */
.page-header {
    text-align: center;
}
  
.page-header h1 {
    margin-bottom: 10%;  /* 或者你需要的具体数值 */
}

.about-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}
  
.about-avatar img {
    border-radius: 50%;
    width: 150px;
    height: 150px;
}
  
.about-bio {
    margin-top: 10%;
}

.about-description {
    text-align: center;
    margin-top: 20px;
    margin-bottom: 20px;
}

修改博客文章链接

参考:https://blog.lxdlam.com/post/9cc3283b/ 来改。

修改模板

archetypes/default.md 中的 front matter 添加下方代码:

slug: {{ substr (sha256 (printf "%s%s" .Date (replace .TranslationBaseName "-" " " | title))) 0 16 }}

这段 Hugo 模板代码用于生成一个独特且简短的标识符(或称为“slug”),用于在网站上唯一标识每个页面。这个标识符是通过对页面的发布日期和标题进行 SHA-256 哈希计算,并取哈希结果的前 16 个字符来生成的。

修改 Hugo config

hugo.yaml 中加入:

permalinks:
  page:
    posts: /post/:slug/

这样以后用 hugo new 生成的文章就会有自动生成的短链接了。

增加评论

使用 giscus 评论系统。在 layouts/partials/comments.html 文件中增加 giscus 提供的 <script> 代码块。

修改 header 条

默认的 header 条会随着下滑消失,想修改为不会消失。

增加 css

assets/css/extended/custom.css 中增加如下代码:

.header {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 1000; 
    background-color: var(--code-bg); 
    border-bottom: 1px solid var(--border);
}

.main {
    margin-top: 5%;
}

h1, h2, h3, h4, h5, h6 {
    scroll-margin-top: calc(var(--header-height) + 1px);
}

修改目录代码(非必要)

我之前设置的目录会与这个有点显示上的冲突,具体表现为下滑一段距离后目录的顶部显示不全,如果你也用了和我一样的修改目录的方法,那你需要修改之前的目录 css 代码,位置为:assets/css/extended/blank.css 找到 .wide .toc 改为:

.wide .toc {
    position: sticky;
    top: 5%;
    border: unset;
    background: unset;
    border-radius: unset;
    width: 100%;
    margin: 0 2px 40px 2px;
}

这样就可以正常显示了。

修改标签页列表展示形式

默认的标签页列表不会显示图片,想改为和首页一样的效果。将 assets/css/common/post-entry.css 中的

.tag-entry .entry-cover {
    display: none;
}

注释掉即可。

渲染数学公式

根据 官方文档 来修改。将下面代码加入到 layouts/partials/extend_footer.html 中:

<script type="text/javascript"
  src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

这样可以渲染 $$ ...$$ 这样的数学公式,如果想使用 inline math 的话需要使用 \\(...\\)

复杂公式渲染

上面的方法可以渲染一些简单的公式,当公式比较复杂,例如:拥有三个以上的花括号时,使用上面的方法会渲染出错。根据这篇文章 来修改,注释掉上述代码,更换为:

<script src="//yihui.org/js/math-code.js" defer></script>
<!-- Just one possible MathJax CDN below. You may use others. -->
<script defer
  src="//mathjax.rstudio.com/latest/MathJax.js?config=TeX-MML-AM_CHTML">
</script>

写简单的公式使用方法和之前一样,当写复杂公式时,需要使用 ` 符号包裹公式,例如:

普通公式为:$$a^2 + b^2 = c^2$$


复杂公式为:`$$a^2 + b^2 = c^2$$`

这样即可正确渲染复杂公式

修改表格渲染

默认的表格渲染没有列边界线,有时看着费劲。将 assets/css/common/post-single.css 中的

.post-content table:not(.highlighttable, .highlight table, .gist .highlight) td {
    min-width: 80px;
    padding: 12px 8px;
    line-height: 1.5;
    border-bottom: 1px solid var(--border);
}

修改为:

.post-content table:not(.highlighttable, .highlight table, .gist .highlight) td {
    min-width: 80px;
    padding: 12px 8px;
    line-height: 1.5;
    /* border-bottom: 1px solid var(--border); */
    border: 1px solid var(--border);
}