偶然看到b站pc版文章页面中调用b站视频的小卡片感觉很好看,想到自己未来也有这样的需求,就尝试写了一个Hexo插件,这里简单介绍一下情况,后面会尝试出一个编写教程!

效果演示

不多bb,开头就演示来一发!

效果咋说呢,还可以吧,目前需要完善移动端显示。
还有就是增加其他类型了,比如文章卡片、Github/npm卡片之类的。
如果你想尝试的话可以直接在你的hexo目录下输入:

1
npm i hexo-bilibili-card

(终于轮到我有这个了好耶!)
欢迎star&贡献代码!!!

心路历程

这个插件的原理其实还是比较简单的,就是从b站的api中获取对应的信息用模板渲染出来对应的信息就是了。
所以我的主要工作就是:写一个卡片的模板,写一个处理b站api的程序。

模板方面

比较简单(但还是写了很久,毕竟我渣渣……)
想看的拿审查元素biubiu一下大概就知道了,不过很多样式其实是直接抄的b站原版(

图片防盗链

还有一点比较值得注意的,就是b站封面的图片服务器不知道为何在首次访问页面的时候会报403,但是第二次就可以正常访问。
这里使用了一个中庸的方法就是使用代理 https://images.weserv.nl/?url={your_img_url} 来解决这个问题,稍微拖慢了一些加载速度。

但是写完html并不只是完了,因为你要通过模板引擎生成,还要适配主题。
模板引擎方面选择的是Hexo目前自带的nunjucks,语法比较简单,主要用到的就是{{里放变量}}然后一些其他杂七杂八的。
主题的适配目前只做了自己的,不过直观感觉大部分主题都能差不多。

信息处理方面

这里把部分代码拿出来说明一下,写的有点乱。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//首先通过hexo的api中的`generator`创建一个虚拟的路由,即把插件中的css样式文件放到public文件夹中
hexo.extend.generator.register('bili_asset', ()=>[
{
path: 'css/bilicard.css',
data: function(){
return fs.createReadStream(
path.resolve(path.resolve(__dirname, "./source"),"bilicard.css"))
}
}
]);
//然后是使用`Tag`创建一个新的标签方便在网页中插入。
hexo.extend.tag.register("bilicard", function (args) {
return bili(args[0]).then(function(bili_card){
//console.log(bili_card);
return bili_card;
});

},{async: true});
//最后使用`fitter`在文章后插入我们css文件的link代码。
hexo.extend.filter.register('after_post_render', (data) => {
let my_css = '<link rel="stylesheet" href="/css/bilicard.css" type="text/css">';
data.content += my_css;
return data;
});

比较值得注意的是第二部分,你会发现我开启了async: true即异步模式。
因为在编写请求api并处理信息的同时,我发现总是无法获得node的request的返回值,这个时候才想起来js中的请求是异步的,所以返回的时候并不一定请求结束,所以在网上搜了许多解决方法最终解决了。
首先展示一下我做的请求部分的代码片段

1
2
3
4
5
6
7
8
9
10
11
var getVideoMessage = (id) => {
return new Promise((resolve, reject) => {
request('http://api.bilibili.com/x/web-interface/view?' + vtype[0] + '=' + id, function (error, response, body) {

}};));
……………………
module.exports = async function createCard(id) {
var card = nunjucks.render(
path.resolve(__dirname, '../templates/' + 'bilicard.njk'), await getVideoMessage(id));
return card;
}

首先内部构造了一个Promise,然后使用await接受参数,最后在上面的index.js里用then来获取参数。这部分由于我也不是理解太透彻暂时不多说(果然还是要多学习呀……)感兴趣的小伙伴欢迎去github看下全部代码顺便给个star

最后

那么基本就这样个情况,后续有啥问题我在更新吧,这期就到这里,祝大家新年快乐!