PaperMod美化归档

主要就是修改归档页面为默认折叠显示,按年月展开 在 layouts\_default\archives.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 155 156 157 158 {{/* layouts/_default/archives.html —— 年→月二级归档 · 默认全部折叠 · 标题在前 · MM-DD后缀 */}} {{define "main" }} <header class="page-header"> <h1>{{ .Title }}</h1> {{if .Description }}<div class="post-description">{{ .Description | markdownify }}</div>{{end }} </header> {{- $pages := where site.RegularPages "Type" "in" site.Params.mainSections }} {{if site.Params.ShowAllPagesInArchive }}{{ $pages := site.RegularPages }}{{ end }} {{- $monthMap := dict "January" "01" "February" "02" "March" "03" "April" "04" "May" "05" "June" "06" "July" "07" "August" "08" "September" "09" "October" "10" "November" "11" "December" "12" }} {{range $pages.GroupByPublishDate "2006" }} {{if ne .Key "0001" }} <section class="archive-year"> <!-- ★ 把所有 open 属性删掉 = 默认折叠 ★ --> <details> <summary class="archive-year-header" id="{{ .Key }}"> <span class="archive-toggle"></span> {{ .Key }} 年 <sup class="archive-count">{{ len .Pages }} 篇</sup> </summary> <div class="archive-year-content"> {{range .Pages.GroupByDate "January" }} {{- $monthNum := index $monthMap .Key }} {{- $monthID := printf "%s-%s" $.Key $monthNum }} <details> <summary class="archive-month-header" id="{{ $monthID }}"> <span class="archive-toggle"></span> {{ .Key }} <sup class="archive-count">{{ len .Pages }} 篇</sup> </summary> <div class="archive-posts"> {{range .Pages.ByPublishDate.Reverse }} {{if eq .Kind "page" }} <article class="archive-entry"> <h3 class="archive-entry-title entry-hint-parent"> <a href="{{ .Permalink }}">{{ .Title | markdownify }}</a> {{if .Draft }}<span class="entry-hint" title="Draft">[草稿]</span>{{end }} <span class="archive-date-postfix"> ・ {{ .PublishDate.Format "01-02" }} </span> </h3> <div class="archive-meta">{{partial "post_meta.html" . -}}</div> <a class="entry-link" aria-label="post link to {{ .Title }}" href="{{ .Permalink }}"></a> </article> {{end }} {{end }} </div> </details> {{end }} </div> </details> </section> {{end }} {{end }} <style> details summary { list-style: none; cursor: pointer; user-select: none; } details summary::-webkit-details-marker { display: none; } .archive-toggle { display: inline-block; width: 1.2em; font-size: 0.85em; margin-right: 0.3em; opacity: 0.8; transition: opacity 0.2s; } details>summary .archive-toggle::before { content: "▶"; } /* 折叠时右箭头 */ details[open]>summary .archive-toggle::before { content: "▼"; } /* 展开时下箭头 */ .archive-year-header { font-size: 1.9em; font-weight: 600; margin: 1.8em 0 0.4em; } .archive-month-header { font-size: 1.55em; font-weight: 600; margin: 1.2em 0 0.4em 1.5em; } .archive-year-content { margin-left: 1.5em; margin-top: -0.4em; } .archive-posts { margin: 0.6em 0 1.8em 3em; padding-left: 0.5em; } .archive-count { font-size: 0.75em; color: var(--secondary); margin-left: 0.5em; font-weight: 500; vertical-align: middle; opacity: 0.9; } .archive-entry-title { font-size: 1.25em !important; margin: 0 0 0.35em !important; font-weight: 600; display: flex; align-items: center; flex-wrap: wrap; gap: 0.8em; } .archive-entry+.archive-entry { margin-top: 1rem; } .archive-date-postfix { font-size: 0.9em; color: var(--secondary); font-weight: normal; opacity: 0.9; flex-shrink: 0; } summary:hover { color: var(--tertiary); } summary:hover .archive-toggle { opacity: 1; } </style> {{end }}

创建: 2025年11月21日 | 更新: 2025年12月04日 | 字数: 700字 | 阅读时长: 2分钟 | Beiyuan

PaperMod修改侧边目录

创建 <your_hugo_site>/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 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 {{- $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; document.addEventListener('DOMContentLoaded', function (event) { checkTocPosition(); elements = document.querySelectorAll('h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]'); if (elements.length > 0) { // 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'); } // Add event listener for the "back to top" link const topLink = document.getElementById('top-link'); if (topLink) { topLink.addEventListener('click', (event) => { // Prevent the default action event.preventDefault(); // Smooth scroll to the top window.scrollTo({ top: 0, behavior: 'smooth' }); }); } }, false); window.addEventListener('resize', function(event) { checkTocPosition(); }, false); window.addEventListener('scroll', () => { // Get the current scroll position const scrollPosition = window.pageYOffset || document.documentElement.scrollTop; // Check if the scroll position is at the top of the page if (scrollPosition === 0) { return; } // Ensure elements is a valid NodeList if (elements && elements.length > 0) { // 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) - scrollPosition) > 0 && (getOffsetTop(element) - scrollPosition) < window.innerHeight / 2) { return element; } }) || activeElement; elements.forEach(element => { const id = encodeURI(element.getAttribute('id')).toLowerCase(); const tocLink = document.querySelector(`.inner ul li a[href="#${id}"]`); if (element === activeElement){ tocLink.classList.add('active'); // Ensure the active element is in view within the .inner container const tocContainer = document.querySelector('.toc .inner'); const linkOffsetTop = tocLink.offsetTop; const containerHeight = tocContainer.clientHeight; const linkHeight = tocLink.clientHeight; // Calculate the scroll position to center the active link const scrollPosition = linkOffsetTop - (containerHeight / 2) + (linkHeight / 2); tocContainer.scrollTo({ top: scrollPosition, behavior: 'smooth' }); } else { tocLink.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 }} 创建 <your_hugo_site>/assets/css/extended/toc.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 77 78 79 80 81 82 83 84 85 86 :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); }

创建: 2025年11月04日 | 更新: 2025年12月04日 | 字数: 1263字 | 阅读时长: 3分钟 | Beiyuan

PaperMod自定义字体

1 . 在 layouts/partials/extend_head.html 中引入 CDN 1 2 3 <!-- 霞鹜字体 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lxgw-wenkai-screen-web/style.css" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@callmebill/lxgw-wenkai-web@latest/style.css" /> 2 . 在 assets/css/extended/custome.css 中添加字体样式: 1 2 3 4 5 6 7 8 9 10 /* 正文字体 */ .post-content { font-family: LXGW WenKai Light, LXGW WenKai Screen, sans-serif; } body { font-size: 18px; line-height: 1.6; font-family: LXGW WenKai Light, LXGW WenKai Screen, sans-serif; } 3 . 在 assets/css/extended/admonition.css 处修改 admonition 注释框中的字体。 1 2 3 4 5 /* admonition注释框字体 */ body, .admonition { font-family: LXGW WenKai Light, LXGW WenKai Screen, sans-serif; }

创建: 2025年11月02日 | 更新: 2025年12月04日 | 字数: 129字 | 阅读时长: 1分钟 | Beiyuan

PaperMod启用评论

1. 创建仓库 该仓库是公开的,否则访客将无法查看 Discussion 2 启用讨论 (1)单击设置 (2)向下滚动到 Features 部分 –> 勾选讨论 –> 点击 Set up Discussions (3)滚动到下方,点击 Start discussions ...

创建: 2025年05月15日 | 更新: 2025年12月04日 | 字数: 1104字 | 阅读时长: 3分钟 | Beiyuan