【笔记】统计Hexo文章实现贡献日历

前言

本文是采集Hexo文章实现贡献日历的进阶版本,无需下载ajax-for-node依赖,无需部署站点地图,可以在不联网的情况下使用,通过在Hexo渲染文章的同时统计文章数,实现渲染贡献日历

编写脚本

  • hexo/scripts目录下创建.js文件作为Hexo脚本
hexo/scripts/GenerateContributeEchartsScript.js
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
const log = require("hexo-log")();
const fs = require("hexo-fs");

/**
* 生成贡献日历
*/
// log.i("开始生成贡献日历");

// 日期计数器
const data_map = new Map();

hexo.extend.filter.register("before_post_render", function (data) {

// 跳过所有非文章的页面
if (!/^_posts\/.*?\.md/.test(data.source)) {
// console.log(data.source, "跳过生成贡献日历")
return data;
}
// console.log(data.source, "执行生成贡献日历")

// 当前文章的创建日期
const post_time_obj = new Date(data.date);
const post_time_string = `${post_time_obj.getFullYear()}-${post_time_obj.getMonth() + 1}-${post_time_obj.getDate()}`;

// 计数器计数
if (data_map.get(post_time_string)) {
// 如果存在当前日期的键就将计数器自增1
data_map.set(post_time_string, data_map.get(post_time_string) + 1);
} else {
// 如果不存在当前日期的键就将计数器置1
data_map.set(post_time_string, 1);
}

log.i(data.source, "贡献日历更新完成");

return data;
});

hexo.extend.filter.register("before_exit", async function (data) {

// 分年度存储计数器
const data_map_year = new Map();

// 从建站那一年元旦遍历到明年元旦的时间,不存在的日期就将计数器置0
const site_data = new Date("2019-11-01");
const start_data = new Date(`${site_data.getFullYear()}-01-01`);
const end_data = new Date(`${new Date().getFullYear() + 1}-01-01`);
for (let i = start_data; i < end_data; i.setDate(i.getDate() + 1)) {
// 当前遍历的年月日
const i_date = `${i.getFullYear()}-${i.getMonth() + 1}-${i.getDate()}`;
// 在分年度存储计数器中是否存在当前年的键,不存在就创建
if (!data_map_year.get(i.getFullYear())) {
data_map_year.set(i.getFullYear(), []);
}
// 计数器中如果不存在当前日期的键值对,就将当前日期的计数器,直接存储到分年度存储计数器中,设置为0
let data_map_year_one = "";
if (!data_map.get(`${i.getFullYear()}-${i.getMonth() + 1}-${i.getDate()}`)) {
data_map_year_one = [i_date, 0];
}
// 计数器中如果存在当前日期的键值对,就将键值对存储到分年度存储计数器中
else {
data_map_year_one = [i_date, data_map.get(`${i.getFullYear()}-${i.getMonth() + 1}-${i.getDate()}`)];
}
data_map_year.get(i.getFullYear()).push(data_map_year_one);
}

// 准备将要写入HTML文件的内容
let file_content_html = "";
// 准备将要写入JS文件的内容
let file_content_js = "/**\n * 渲染贡献日历\n */\n";
// 定义HTML头部,引入echarts.js
file_content_html += "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\"\n content=\"width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\n <title>貢獻</title>\n</head>\n<body>\n";
for (let year = new Date().getFullYear(); year >= site_data.getFullYear(); year--) {
// 循环写入每一年的数据
file_content_html += `\n<h2>${year}年度</h2>\n<div id="app-contribute-${year}" style="width: 100%; height: 100%;"></div>\n`;
file_content_js += `\nif (document.getElementById("app-contribute-${year}") !== null) {\n echarts.init(document.getElementById("app-contribute-${year}")).setOption({\n /* 悬浮窗 */\n tooltip: {\n padding: 10,\n borderColor: "#FFF",\n borderWidth: 1,\n formatter: function (param) {\n return \`<div style="font-size: 14px;">\${param.value[0]}: \${param.value[1]}</div>\`;\n }\n },\n visualMap: {\n show: false,\n min: 1,\n max: 5,\n minOpen: true,\n maxOpen: true,\n calculable: false,\n inRange: {\n symbol: "rect",\n color: ["#ebedf0", "#c6e48b", "#7bc96f", "#239a3b", "#196127"]\n },\n itemWidth: 12,\n itemHeight: 12,\n type: "piecewise",\n orient: "horizontal",\n left: "center",\n top: 0\n },\n /* 主体 */\n calendar: {\n top: 0,\n range: "${year}",\n left: "center",\n cellSize: [13, 13],\n splitLine: {\n /* 月份分割线 */\n show: false\n },\n name: {\n textStyle: {\n color: "#3C4858"\n }\n },\n itemStyle: {\n borderColor: "#fff",\n borderWidth: 2\n },\n yearLabel: {\n /* 左侧年份 */\n show: false\n },\n monthLabel: {\n /* 上面月份 */\n show: false\n },\n dayLabel: {\n /* 左侧星期 */\n show: false\n }\n },\n series: {\n type: "heatmap",\n coordinateSystem: "calendar",\n calendarIndex: 0,\n data: ${JSON.stringify(data_map_year.get(year))}\n }\n });\n}\n`;
}
// 定义HTML尾部
file_content_html += "\n</body>\n</html>";
// 写入文件
fs.writeFile("./source/contribute/index.html", file_content_html);
fs.writeFile("./source/contribute/index.js", file_content_js);

log.i("贡献日历写入文件完成");
});

完成