Hexo里优雅地使用emoji

blog_emoji

最近在思考如何在文章中方便的使用emoji表情图标,整体大概有这些思路:

  1. 做成font awesome的形式,通过class名调用。这也是之前采用的方式,将css里定义的所有图标做成一个cheat sheet,直接复制源码插入文章就可以。优点是语义化,常用的几个不用参照表就能盲打出来,而且图标已经加载到css中,不占用额外的资源和带宽。缺点也很明显:不是所有emoji都能做成字体,自定义起来略繁琐。而且可移动性差,用typora编辑md文件时不能所见即所得。
  2. 使用hexo自带的Tag Plugins。和CSS的方法类似,虽然用起来方便,但灵活性和可移植性差了点。
  3. 直接插入img标签外部引入。这也是本文要提到的方式,可移植性好,扩容也比较方便。剩下就是如何操作的问题了。最简单粗暴的就是做一张cheet sheet把所有emoji都放上去,然后定义一些操作逻辑,比如点击某个图片复制它的标签源码。接下来的问题就是如何获取emoji并且把list放到html中。这里介绍三个实用的浏览器扩展,解决思路也不一样。

插件一:DownThemAll!

源自Firefox的高质量下载器辅助类工具。本身是调用浏览器自带的下载功能,最有特点的功能是可以定义序列化url,比如
http://path-to-file/1.png
http://path-to-file/2.png

http://path-to-file/20.png
这种就可以写成http://path-to-file/[1:20].png,并且可以定义命名规则,非常适合用来批量抓取资源。而且它本身就可以嗅探网页上的各种文件,筛选器也很强大。本来有这样一个工具就可以爬到各大社交网站的表情库了。然而试下来发现一个图都下不动,不知道是不是网络原因。所以就有了第二个。

插件二:Save All Resources

顾名思义,只要网站能打开,图标能显示,它就能把所有东西都保存到本地,并且不需要再次请求网络。最后就是用这种方式爬下了几个网站的emoji,而且下载下来就已经按照文件夹整理好了。全部完成后在DOS里用dir /s /b列出所有文件的路径,稍微查找替换就做好了一个list。再介绍另外一个有意思的工具。

插件三:Save Page WE

一键将当前网页保存到一个html文件中,所有的图片通过dataURI直接内嵌,理论上视频也是可以的,没尝试过。这样做好的cheat sheet可以保存到本地,只需一个文件就能离线查看。当然,复制img标签的时候src也是base64编码的。

插件四:Scrapper

老插件了,但依然可用,以b站为例

1
2
Selector ⇢ jQuery ⇢ a.emoji-list>img
Columns ⇢ @src @title

获得url和图片名的表格,然后在编辑器里替换成aria2c http://url-to-emoji -o xxx.png的形式,复制后在cmd里执行即可。这里有个在线工具可以把汉字转换为拼音,同样在编辑器里查找替换成ren 汉字.png hanzi.png这种形式,然后执行。

回到cheet sheet的制作,有了url list再简单排版下就大功告成了。这里用<ul>标签简单做了个flex布局,够用就好。最后就是复制的逻辑问题了,复制到剪切板的代码实现通过google获得:

1
2
3
4
5
6
7
8
9
function copyToClipboard(text) {
var dummy = document.createElement("textarea");
document.body.appendChild(dummy);
dummy.value = text;
dummy.select();
document.execCommand("copy");
document.body.removeChild(dummy);
alert('复制成功:' + text)
}

再贪心一点,除了复制图片链接,还想实现复制为dataURI的形式,比如直接点击是复制链接,shift加点击是复制dataURI。网上大多是通过canvas的toDataURL接口实现的,好处是不用再fetch一次,但我测试下来MIME参数无效,而且转码也有点问题。最后还是上fetch方法

1
2
3
4
5
6
7
8
9
10
11
12
const getBase64FromUrl = async (url) => {
const data = await fetch(url);
const blob = await data.blob();
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
const base64data = reader.result;
resolve(base64data);
}
});
}

不知道转Base64有没有可能本地实现,稍微搜了下没有头绪遂放弃。

这里只是提供思路,成品就不放出来了(版权警告

更新

6.13 增加插件Scrapper