Hexo博客(21)博客概览插件
早就有这个想法了,汇总博客的统计量,比如总共有多少篇文章、最近一次更新是哪天,然后展示在主页上,让人能一眼看出博客的活跃状态。
动手之前感觉这件事情并不难,就是一些html,js,css语句,并且这也不是我第一次给自己的博客写插件了,但过程中还是遇到一些问题,都查资料解决了,做完后感觉还是有很多收获。
获取站点文章总数
文章总数很好获得,Hexo提供一个变量site.posts
,是一个数组,其长度就是文章总数,然后使用ejs语句<%= site.posts.length %>
输出即可。
获取站点最近更新日期
把站点所有文章按更新日期倒序排序,取第一个,获取其更新日期,就是整个博客的最近更新日期。
排序使用ejs的sort()
函数,取数组的第一个用ejs的first()
函数,都很方便,如下:
<!-- 最近更新日期,把站点所有文章按更新日期(updated)倒序排序,取第一个 -->
var recent_updated_date = site.posts.sort('updated', -1).first().updated.format('YYYY年MM月DD日');
不过我第一次写的时候,对ejs也不熟悉(当然现在也不熟悉),从网上查到一个first()
函数,但用的时候忘了加括号,总是报错。
统计一年(一月)内新增文章数
逻辑也很简单,还是遍历站点所有文章,将其发布日期和指定日期作比较病计数。
但实际写起来绕了个弯,一开始想的比较复杂,把文章的年、月、日都获取到,和计算好的一年前时间的年、月、日分别比较,这样写逻辑非常复杂,还总出错。
后来上网查了查JavaScript的Date
对象,发现是可以直接比较大小的,然后就很简单了:
<!-- 最近一年的文章数 -->
var one_year_count=0;
<!-- 最近30天的文章数 -->
var one_month_count=0;
var nowdate = new Date(); <!-- 当前日志的Date对象 -->
var one_year_ago = new Date(nowdate-365*24*60*60*1000); <!-- 一年前的Date对象 -->
var one_month_ago = new Date(nowdate-30*24*60*60*1000); <!-- 30天前的Date对象 -->
<!-- 遍历站点所有文章,按日期统计 -->
site.posts.forEach(function(post){
var post_date = post.date.toDate(); <!-- 文章的发表日期Date对象 -->
if (post_date > one_year_ago){ <!-- Date对象可直接比较 -->
one_year_count = one_year_count+1;
}
if (post_date > one_month_ago){ <!-- Date对象可直接比较 -->
one_month_count = one_month_count+1;
}
});
有个问题,文章数的统计是每次博客生成触发的,不是实时的。也就是说是以hexo g
生成博客内容的时间作为当前时间统计的个数,部署后不会自动刷新。曾经想改为页面刷新时重新统计,发现做不到,在js函数中是引用不到hexo提供的site
变量的,只在构建环境中才能读到。
JavaScript实时动态显示当前时间
最后还给这个小插件加了个花哨功能,使用JavaScript动态实时的显示当前时间。
实现步骤如下:
- 1、写一个表示当前时间的
<span></span>
,指定id为now_time_span,内容先空着,在后面的js函数中设置此id的内容。 - 2、写一个js函数
showNowTime()
,设置id为now_time_span的html元素的内容为格式化的当前时间。 - 3、设置一个js定时器,每1000毫秒触发一次,调用
showNowTime()
函数。
代码如下:
<!-- 在此位置插入一个表示当前时间的span,指定id,在后面的js函数中设置此id的内容 -->
<span id="now_time_span"></span>
<script type="text/javascript">
<!-- 自定义JavaScript日期格式 -->
<!-- (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 -->
<!-- (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18 -->
Date.prototype.Format = function (fmt) { //author: meizz
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
<!-- js函数,设置id为now_time_span的html元素的内容为格式化的当前时间 -->
function showNowTime(){
document.getElementById("now_time_span").innerText = "当前时间:"+new Date().Format("yyyy-MM-dd hh:mm:ss");
}
<!-- 立即调用一次showNowTime()函数,给now_time_span赋初始值 -->
showNowTime();
<!-- js定时器,每1000毫秒触发一次,调用showNowTime()函数 -->
setInterval("showNowTime()",1000);
</script>
其中有个比较复杂的自定义JavaScript Date格式的函数,从网上找的。
侧边栏加载overview插件
以下针对freemind/free2mind主题,其他主题请自行更改。
在themes\free2mind\layout\_widget目录下新建ejs脚本文件overview.ejs,写入上述所有代码。
在主题配置文件themes\free2mind_config.yml中,widgets
配置项下新增overview插件,使得插件能被加载。
overview.ejs完整代码如下:
<!-- 2018.2.10,masikkk新增,添加博客概览侧边栏 -->
<div class="widget">
<h4><%= __('博客概览') %></h4>
<ul class="blogroll list-unstyled">
<%
<!-- 最近更新日期,把站点所有文章按更新日期(updated)倒序排序,取第一个 -->
var recent_updated_date = site.posts.sort('updated', -1).first().updated.format('YYYY年MM月DD日');
<!-- 最近一年的文章数 -->
var one_year_count=0;
<!-- 最近30天的文章数 -->
var one_month_count=0;
var nowdate = new Date(); <!-- 当前日志的Date对象 -->
var one_year_ago = new Date(nowdate-365*24*60*60*1000); <!-- 一年前的Date对象 -->
var one_month_ago = new Date(nowdate-30*24*60*60*1000); <!-- 30天前的Date对象 -->
<!-- 遍历站点所有文章,按日期统计 -->
site.posts.forEach(function(post){
var post_date = post.date.toDate(); <!-- 文章的发表日期Date对象 -->
if (post_date > one_year_ago){ <!-- Date对象可直接比较 -->
one_year_count = one_year_count+1;
}
if (post_date > one_month_ago){ <!-- Date对象可直接比较 -->
one_month_count = one_month_count+1;
}
});
%>
本博客共有文章<%= site.posts.length %>篇,最近更新日期<%= recent_updated_date %>,最近一年新增文章<%= one_year_count %>篇,最近30天新增文章<%= one_month_count %>篇。
</ul>
<!-- 在此位置插入一个表示当前时间的span,指定id,在后面的js函数中设置此id的内容 -->
<span id="now_time_span"></span>
<script type="text/javascript">
<!-- 自定义JavaScript日期格式 -->
<!-- (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 -->
<!-- (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18 -->
Date.prototype.Format = function (fmt) { //author: meizz
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
<!-- js函数,设置id为now_time_span的html元素的内容为格式化的当前时间 -->
function showNowTime(){
document.getElementById("now_time_span").innerText = "当前时间:"+new Date().Format("yyyy-MM-dd hh:mm:ss");
}
<!-- 立即调用一次showNowTime()函数,给now_time_span赋初始值 -->
showNowTime();
<!-- js定时器,每1000毫秒触发一次,调用showNowTime()函数 -->
setInterval("showNowTime()",1000);
</script>
</div>
效果图如下:
博客概览侧边栏插件
参考
EJS - An open source JavaScript Template library
http://www.embeddedjs.com/
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: