给 Hugo 博客归档页加上 Github 风格热力图

最近看着博客的归档页面,总觉得光秃秃的列表差点意思。平时经常看 Github 主页那块绿色的代码提交热力图(Heatmap),看着自己的“绿格子”一天天变多,那种正反馈确实挺让人上瘾的。 于是就萌生了一个想法:能不能在我的博客归档页也加一个类似 Github 风格的文章更新热力图? 折腾了一番后,完美搞定。这篇文章记录一下具体的实现过程。 需求分析 在动手之前,我给自己定了几个硬性要求: 零依赖,不拖慢速度:网上很多教程教的是用 ECharts 之类的图表库。虽然效果好,但为了一个小图引入这么大的库,对静态博客的加载速度很不友好。我要用纯原生 JS 和 CSS 来画。 主题适配:我的博客用的是 PaperMod 主题,支持暗黑模式切换。这个热力图必须能无缝跟着主题切换颜色。 响应式布局,拒绝丑陋的滚动条:手机端和电脑端屏幕宽度不一样。我不希望在手机上出现一个很长很长的横向滚动条。它必须能根据当前窗口的宽度,自动计算并显示能够放得下的“周数”。 边缘防遮挡的悬浮提示:鼠标放上去要能显示当天的文章信息,而且如果是最右侧(今天)或者最顶部的数据,提示框不能被屏幕边缘截断。 动手实现 Hugo 的修改逻辑很简单,不要去动 themes/ 目录下的源码,而是利用它的覆盖机制。 把 themes/PaperMod/layouts/_default/archives.html 复制到项目根目录的 layouts/_default/archives.html。接下来所有的修改都在这个本地文件里进行。 1. 数据获取 第一步是把博客里所有文章的日期拿出来。这一步利用 Hugo 强大的模板语法,在 HTML 里直接把数据渲染成 JS 的数组: <script> const postsData = [ {{- range where site.RegularPages "Type" "in" site.Params.mainSections }} { date: "{{ .Date.Format "2006-01-02" }}", title: "{{ .Title | htmlEscape }}" }, {{- end }} ]; // 按日期归类统计 const postMap = new Map(); postsData.forEach(p => { if (!postMap.has(p.date)) postMap.set(p.date, []); postMap.get(p.date).push(p); }); </script> 这段代码会在编译时把所有文章遍历一遍,最终生成一个干净的 JSON 数据交给浏览器的 JS 处理。 ...

March 28, 2026