标签外挂是 Hexo 独有的功能,并不是标准的 Markdown 格式。
以下的写法,只适用于 Butterfly 主题,用在其它主题上不会有效果,甚至可能会报错。使用前请留意
Butterfly主题 自带的标签外挂
More info
Butterfly 文档(四) 标签外挂
Jerry
推荐添加的标签外挂
哔哩哔哩卡片标签外挂
效果
添加方法
bilibili.js
在[blogroot]\themes\butterfly\scripts\tag下新建文件bilibili.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
| 'use strict' let playIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" class="icon"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.67735 4.2798C5.98983 4.1725 7.85812 4.0625 10 4.0625C12.1421 4.0625 14.0105 4.17252 15.323 4.27983C16.2216 4.3533 16.9184 5.04049 16.9989 5.9318C17.0962 7.00837 17.1875 8.43614 17.1875 10C17.1875 11.5639 17.0962 12.9916 16.9989 14.0682C16.9184 14.9595 16.2216 15.6467 15.323 15.7202C14.0105 15.8275 12.1421 15.9375 10 15.9375C7.85812 15.9375 5.98983 15.8275 4.67735 15.7202C3.77861 15.6467 3.08174 14.9593 3.00119 14.0678C2.90388 12.9908 2.8125 11.5627 2.8125 10C2.8125 8.43727 2.90388 7.00924 3.00119 5.93221C3.08174 5.04067 3.77861 4.35327 4.67735 4.2798ZM10 2.8125C7.81674 2.8125 5.9136 2.92456 4.5755 3.03395C3.07738 3.15643 1.8921 4.31616 1.75626 5.81973C1.65651 6.92379 1.5625 8.39058 1.5625 10C1.5625 11.6094 1.65651 13.0762 1.75626 14.1803C1.8921 15.6838 3.07738 16.8436 4.5755 16.966C5.9136 17.0754 7.81674 17.1875 10 17.1875C12.1835 17.1875 14.0868 17.0754 15.4249 16.966C16.9228 16.8436 18.108 15.6841 18.2438 14.1807C18.3435 13.077 18.4375 11.6105 18.4375 10C18.4375 8.38948 18.3435 6.92296 18.2438 5.81931C18.108 4.31588 16.9228 3.15645 15.4249 3.03398C14.0868 2.92458 12.1835 2.8125 10 2.8125ZM12.1876 10.722C12.7431 10.4013 12.7431 9.59941 12.1876 9.27866L9.06133 7.47373C8.50577 7.15298 7.81133 7.55392 7.81133 8.19542V11.8053C7.81133 12.4468 8.50577 12.8477 9.06133 12.527L12.1876 10.722Z" fill="#9499A0"/></svg>` let likeIcon = `<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg" class="icon"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.77234 30.8573V11.7471H7.54573C5.50932 11.7471 3.85742 13.3931 3.85742 15.425V27.1794C3.85742 29.2112 5.50932 30.8573 7.54573 30.8573H9.77234ZM11.9902 30.8573V11.7054C14.9897 10.627 16.6942 7.8853 17.1055 3.33591C17.2666 1.55463 18.9633 0.814421 20.5803 1.59505C22.1847 2.36964 23.243 4.32583 23.243 6.93947C23.243 8.50265 23.0478 10.1054 22.6582 11.7471H29.7324C31.7739 11.7471 33.4289 13.402 33.4289 15.4435C33.4289 15.7416 33.3928 16.0386 33.3215 16.328L30.9883 25.7957C30.2558 28.7683 27.5894 30.8573 24.528 30.8573H11.9911H11.9902Z"></path></svg>` let coinIcon = `<svg width="28" height="28" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="icon" style="fill:;"><path fill-rule="evenodd" clip-rule="evenodd" d="M14.045 25.5454C7.69377 25.5454 2.54504 20.3967 2.54504 14.0454C2.54504 7.69413 7.69377 2.54541 14.045 2.54541C20.3963 2.54541 25.545 7.69413 25.545 14.0454C25.545 17.0954 24.3334 20.0205 22.1768 22.1771C20.0201 24.3338 17.095 25.5454 14.045 25.5454ZM9.66202 6.81624H18.2761C18.825 6.81624 19.27 7.22183 19.27 7.72216C19.27 8.22248 18.825 8.62807 18.2761 8.62807H14.95V10.2903C17.989 10.4444 20.3766 12.9487 20.3855 15.9916V17.1995C20.3854 17.6997 19.9799 18.1052 19.4796 18.1052C18.9793 18.1052 18.5738 17.6997 18.5737 17.1995V15.9916C18.5667 13.9478 16.9882 12.2535 14.95 12.1022V20.5574C14.95 21.0577 14.5444 21.4633 14.0441 21.4633C13.5437 21.4633 13.1382 21.0577 13.1382 20.5574V12.1022C11.1 12.2535 9.52148 13.9478 9.51448 15.9916V17.1995C9.5144 17.6997 9.10883 18.1052 8.60856 18.1052C8.1083 18.1052 7.70273 17.6997 7.70265 17.1995V15.9916C7.71158 12.9487 10.0992 10.4444 13.1382 10.2903V8.62807H9.66202C9.11309 8.62807 8.66809 8.22248 8.66809 7.72216C8.66809 7.22183 9.11309 6.81624 9.66202 6.81624Z"></path></svg>`
function bilibili(args) { const id = args[0].replace(/.*video\/(.*)\/?.*/, '$1') const time = args[1] const hidden_desc = args[2] return ` <a href="https://www.bilibili.com/video/${id}/" class="bilibili_box" id="${id}"></a>
<script> bilibili() function bilibili() { let dom = document.getElementById('${id}') fetch('https://bilibili.o0w0b.top/api/b?id=${id}').then(res=>res.json()).then(data=>{ dom.innerHTML = \` <div class="bilibili_cover"> <img src="https://s1.hdslb.com/bfs/static/player/img/play.svg" class="play_icon no-lazyload"> <img src="\${data.pic + '&h=300'}" class="no-lazyload"> ${time ? `<span>${time}</span>` : ''} </div> <div class="bilibili_info"> <div class="title">\${data.title}</div> ${hidden_desc == 'true' ? '' : '<div class="desc">\${data.desc}</div>'} <div class="stat"> <span>${playIcon}\${data.view}</span> <span>${likeIcon}\${data.like}</span> <span>${coinIcon}\${data.coin}</span> </div> <div class="owner"> <span class="tip">视频</span> <img src="\${data.face + '&h=100'}" class="no-lazyload"> <span>\${data.owner}</span> </div> </div> \` }) } </script> ` }
hexo.extend.tag.register('bilibili', bilibili, { ends: false })
|
bilibili.styl
在[blogroot]\themes\butterfly\source\css\_tags下新建文件bilbili.styl并粘贴如下代码:
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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| .bilibili_box display: flex background: var(--card-bg) border: 1px solid #e0e3ed border-radius: 10px overflow: hidden color: var(--font-color) !important text-decoration: none !important transition: .3s &:hover border-color: #4976f5 +maxWidth768() flex-direction: column .bilibili_cover width: 234px position relative +maxWidth768() width: 100% img width: 100% filter: none margin: 0 !important border-radius: 0 !important .play_icon position: absolute width 45px height 45px opacity .8 top: 50% left 50% transform: translate(-50%,-50%) span position: absolute bottom: 0px right: 5px color: white text-shadow: 0 1px 3px #7a7a7a .bilibili_info padding: 10px 10px 10px 18px line-height: 1 width: calc(100% - 200px) display: flex flex-direction: column justify-content: space-around +maxWidth768() width: 100% padding-bottom: 25px line-height: 1.5 .title font-size: 1.2rem font-weight: bold white-space: nowrap overflow: hidden text-overflow: ellipsis line-height: 1.5 .desc font-size: 15px margin: 2px 0 4px white-space: nowrap overflow: hidden text-overflow: ellipsis +maxWidth768() white-space: normal display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; .stat font-size: 15px svg margin-right: 3px font-size: 18px width: 1em height: 1em path fill: var(--font-color) span margin-right: 10px display: inline-flex align-items: center .owner display: flex align-items: center line-height: 1 font-size: 15px .tip color: #FF6699 border: 1px solid padding: 3px 6px font-size: 12px border-radius: 5px margin-right: 10px img width 22px height: 22px border-radius: 50% !important object-fit: cover margin 0 5px 0 0 !important
[data-theme='light'] .bilibili_box .bilibili_info .stat svg, [data-theme='dark'] .bilibili_cover opacity .8
|
使用方法
使用此标签外挂只需要填写视频链接,填写后将会自动获取信息
视频时长因为不容易通过 api 获取,所以设置成了手动填写
1
| {% bilibili 视频链接 视频时长 是否隐藏简介 %}
|
若需要隐藏简介,在后面添加 true,默认不隐藏简介
1 2 3
| {% bilibili https://www.bilibili.com/video/BV1NT411C7wS 25:01 %} <!-- 如果想要隐藏简介,添加true即可(注意,要隐藏简介则必须填写视频时间!),如下 --> {% bilibili https://www.bilibili.com/video/BV1NT411C7wS 25:01 true %}
|
同一个视频的卡片不能同时显示, 如果同时设置多个同一个视频的卡片,
只会在第一个位置显示,且会根据最后一个的设置决定是否隐藏简介
隐藏简介后的效果
关于用到的API
API地址:https://bilibili.o0w0b.top/api/b
id
bilibili 视频ID
t
请求单个数据的类型,可选值如下
| 值 |
备注 |
| owner |
视频作者名 |
| face |
视频作者头像 |
| title |
视频标题 |
| desc |
视频简介 |
| pic |
视频封面 |
| view |
观看数量 |
| like |
点赞数 |
| coin |
投币数 |
| danmaku |
弹幕数 |
| favorite |
收藏数 |
| reply |
评论数量 |
| share |
分享数量 |
示例:
- https://bilibili.o0w0b.top/api/b?id=BV1h84y1Y7nn
会返回视频的所有数据
- https://bilibili.o0w0b.top/api/b?id=BV1h84y1Y7nn&t=view
会返回视频的观看数量
自建API
安装Vercel CLI
打开终端,运行如下命令
初始化项目
新建一个文件夹,然后在此文件夹中打开终端
运行如下命令,然后重复按回车
安装axios
运行如下命令
创建文件

新建 api 目录,然后在 api 目录下创建如下两个文件
创建的文件名字对应你后期的 api 路径名,如 b.js 对应 xxx.top/api/b
另外,index.js 文件对应的是 xxx.top/api
b.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
| const axios = require('axios') module.exports = async (req, res) => { if (req.method === 'GET') { if (req.query.id) { let { data } = await axios.get('https://api.bilibili.com/x/web-interface/view?bvid=' + req.query.id) data = data.data let ls = { owner: data.owner.name, face: "https://images.weserv.nl/?url=" + data.owner.face, title: data.title, desc: data.desc, pic: "https://images.weserv.nl/?url=" + data.pic, coin: data.stat.coin, danmaku: data.stat.danmaku, favorite: data.stat.favorite, like: data.stat.like, reply: data.stat.reply, share: data.stat.share, view: data.stat.view, } if (req.query.t) { return res.send(ls[req.query.t]) } else return res.send(JSON.stringify(ls)) } else { return res.send('Hi Bilibili') } } }
|
index.js
为了避免访问 xxx.top/api 报错,我们给它也添加一个内容使其返回 Hi Bilibili
1 2 3
| module.exports = (req, res) => { return res.status(200).send('Hi Bilibili') }
|
在根目录下创建 vercel.json 文件并粘贴如下代码:
(这一步是为了防止跨域)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| { "headers": [ { "source": "/api/(.*)", "headers": [ { "key": "Access-Control-Allow-Origin", "value": "*" }, { "key": "Access-Control-Allow-Headers", "value": "X-Requested-With, Content-Type, Authorization" }, { "key": "Access-Control-Allow-Credentials", "value": "true" } ] } ] }
|
部署
在部署前先运行如下命令来测试代码是否生效
第一次运行会让登录和创建项目,登录的话选择你平时登录的方式,例如:github ,在浏览器完成授权就登录成功了。创建项目就重复按回车即可。
运行如下命令,然后重复按回车
测试index.js:浏览器打开http://localhost:3000/api ,页面正常会显示 Hi Bilibili
测试b.js:http://localhost:3000/api/b?id=BV1h84y1Y7nn ,页面正常会显示相应数据
本地测试没问题了就可以运行如下命令进行线上部署了
vercel提供的网址在国内无法访问,需要绑定一个自己的域名
链接卡片标签外挂
效果
添加方法
link.js
在[blogroot]\themes\butterfly\scripts\tag下新建文件link.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
|
'use strict'
let defaultIcon = "https://imgbed.o0w0b.top/file/1764343661265_image.png";
function link(args) { args = args.join(' ').split(',');
let title = (args[0] || '点击直达链接').trim(), desc = (args[1] || '').trim(), url = (args[2] || '').trim(), urlNoProtocol = url.replace(/^https?\:\/\//i, ""), imgUrl = (args[0] ? "https://www.faviconextractor.com/favicon/" + urlNoProtocol : defaultIcon).trim();
let favicon = `<img src="${imgUrl}" class="no-lightbox" onerror="this.src='${defaultIcon}'">`;
return `<a href="${url}" ${url.includes('http') ? 'target="_blank"' : ''} title="${title}" referrerPolicy="no-referrer" class="link_card"> <div class="link_icon">${favicon}</div> <div class="link_content"> <div class="link_title">${title}</div> ${desc ? `<div class="link_desc">${desc}</div>` : ''} </div> </a>`; }
hexo.extend.tag.register('link', link, { ends: false })
|
link.styl
在[blogroot]\themes\butterfly\source\css\_tags下新建文件link.styl并粘贴如下代码:
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
| .link_card display: flex margin: 10px 0 color: var(--font-color) !important text-decoration: none !important background: var(--reward-pop) border-radius: 10px padding: 12px &:hover background: #9370DB color: white !important .link_icon,.link_content height: 4rem .link_icon img,svg height: 4rem width: 4rem .link_content margin-left: 1rem width: calc(100% - 6rem) overflow: hidden line-height: 1.5 display: flex flex-direction: column justify-content: center .link_title font-weight: bold font-size: 1.2rem .link_title,.link_desc word-break: break-all overflow:hidden text-overflow: ellipsis &:not(:has(.link_desc)) .link_title display:-webkit-box -webkit-box-orient:vertical -webkit-line-clamp:2 .link_desc opacity: .6 .link_desc,&:has(.link_desc) .link_title white-space: nowrap
|
使用方法
链接的开头需要加https,例如:https://o0w0b.top
不加https的效果请自行尝试
使用时,这三个参数虽然不需要全写,但位置一定要留出来
该方式的标题默认为 “点击直达链接”,图标为未能获取网站图标时的默认图标
1
| {% link ,,https://o0w0b.top %}
|
效果:
1
| {% link o0w0b的主页,, https://o0w0b.top %}
|
效果: