2

【笔记】采集Hexo文章实现贡献日历

 1 year ago
source link: https://loli.fj.cn/2023/06/18/%E9%87%87%E9%9B%86Hexo%E6%96%87%E7%AB%A0%E5%AE%9E%E7%8E%B0%E8%B4%A1%E7%8C%AE%E6%97%A5%E5%8E%86/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

编写Hexo插件,通过采集sitemap.txt站点地图中的文章创建日期作为数据,通过Echarts的日历热力图(Calendar Heatmap)渲染图表,实现贡献日历

  • 已部署的站点可以访问站点地图(/sitemap.txt

创建贡献页面

hexo new page contribute
npm install ajax-for-node
npm install hexo-fs
  • hexo/scripts目录下创建.js文件作为Hexo脚本

site:这个常量要改成自己的站点域名
start_data:这个常量要改成自己的建站时间

hexo/scripts/GenerateContributeEchartsScript.js

const nodeAjax = require('ajax-for-node');
const fs = require('hexo-fs');

// 站点根目录
const site = `https://loli.fj.cn`;
// 站点地图路径
const site_map = `${site}/sitemap.txt`;
// 正则表达式
const reg = /\d{4}\/\d{2}\/\d{2}/;
// 建站时间
const start_data = new Date("2019-11-22");
// 所有日期
let data_list = [];
// 日期计数
let data_map = new Map();
// 分年度存储
let data_map_year = new Map();
// 文件内容
let file_content = ""

nodeAjax({
url: site_map,
type: "GET",
processData: false,
contentType: false,
success: function (result) {
const lines = result.split("\n");
// 过滤结果
for (let line of lines) {
if (reg.test(line)) {
line = line.substr(19, 10);
line = line.replaceAll("/", "-");
data_list.push(line);
}
}
// 遍历结果集,将所有得到的日期计数
for (const item of data_list) {
if (data_map.get(item)) {
// 能得到日期,将计数器自增1
data_map.set(item, data_map.get(item) + 1);
} else {
// 不能得到日期,将计数器置1
data_map.set(item, 1);
}
}
// 将所有计数的日期计为0
// 从建站那一年元旦便利到明年元旦的时间
let current_data = new Date(`${start_data.getFullYear()}-01-01`);
// 明年元旦
const end_data = new Date(`${new Date().getFullYear() + 1}-01-01`);
while (current_data.getTime() < end_data.getTime()) {
// 遍历的时间的年月日
const year = current_data.getFullYear();
const month = current_data.getMonth() + 1 < 10 ? '0' + (current_data.getMonth() + 1) : current_data.getMonth() + 1;
const day = current_data.getDate().toString().length === 1 ? "0" + current_data.getDate() : current_data.getDate();
const current = `${year}-${month}-${day}`
// 不能得到日期,将计数器置0
if (data_map.get(current) === undefined) {
data_map.set(current, 0);
}
// 自增1天
current_data.setDate(current_data.getDate() + 1);
}
// 分年度存储
// 从建站那一年遍历到今年
for (let currentYear = start_data.getFullYear(); currentYear < end_data.getFullYear(); currentYear++) {
if (!data_map_year.get(currentYear)) {
// 如果还没有当前年度的数据,就新增一个数组
data_map_year.set(currentYear, [])
}
// 遍历所有处理后的数据,将当前年的数据全部转移
data_map.forEach((value, key) => {
if (key.indexOf(currentYear) !== -1) {
const data = [key, value];
data_map_year.get(currentYear).push(data);
}
})
// console.log(data_map_year.get(currentYear));
}
// 准备将要写入文件的内容
file_content += `---\ntitle: 贡献\n---\n`;
// 从建站那一年遍历到今年
for (let currentYear = start_data.getFullYear(); currentYear < end_data.getFullYear(); currentYear++) {
file_content += `\n## ${currentYear}年度\n\n{% echarts 700 100 %}\n{\n // 悬浮窗\n tooltip: {\n padding: 10,\n borderColor: "#FFF",\n borderWidth: 1,\n formatter: function (a) {\n var b = a.value;\n return \`<div style="font-size: 14px;">\${b[0]}: \${b[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: "${currentYear}",\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(currentYear))}\n }\n}\n{% endecharts %}\n`;
}
// 写入文件
fs.writeFile("./source/contribute/index.md", file_content);
}
});

渲染后的结果

---
title: 貢獻
comments: false
---

## 2019年度

{% echarts 700 100 %}
{
// 悬浮窗
tooltip: {
padding: 10,
borderColor: "#FFF",
borderWidth: 1,
formatter: function (a) {
var b = a.value;
return `<div style="font-size: 14px;">${b[0]}: ${b[1]}</div>`;
}
},
visualMap: {
show: false,
min: 1,
max: 5,
minOpen: true,
maxOpen: true,
calculable: false,
inRange: {
symbol: "rect",
color: ["#ebedf0", "#c6e48b", "#7bc96f", "#239a3b", "#196127"]
},
itemWidth: 12,
itemHeight: 12,
type: "piecewise",
orient: "horizontal",
left: "center",
top: 0
},
// 主体
calendar: {
top: 0,
range: "2019",
left: "center",
cellSize: [13, 13],
splitLine: {
// 月份分割线
show: false
},
name: {
textStyle: {
color: "#3C4858"
}
},
itemStyle: {
borderColor: "#fff",
borderWidth: 2
},
yearLabel: {
// 左侧年份
show: false
},
monthLabel: {
// 上面月份
show: false
},
dayLabel: {
// 左侧星期
show: false
}
},
series: {
type: "heatmap",
coordinateSystem: "calendar",
calendarIndex: 0,
// 此处的数据以实际为准,此处只作为范例展示
data: [["2019-01-01",1],["2019-01-02",2]]
}
}
{% endecharts %}

小冰博客
Zfour/hexo-github-calendar
Kaiboshi的博客
HCLonely/hexo-calendar


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK