在Hexo博客里插入Emoji表情

此方法已经失效!!!!!

由于 Emoji 表情实在是太魔性了,有些东西不用它还真的难以用语言来表达出来。

起初我以为在 Hexo 博客里插入 Emoji 是一件极其简单的事情。貌似 Jekyll 直接就支持 :joy:这种双冒号的书写形式,然后在它渲染 Markdown 文件的时候,会自动转换成相关的 HTML 标签,插入一个 Emoji。
后来我在 Hexo 博客里尝试了一下,果然,没成功(成功了就不叫折腾了= =),Hexo 只是原封不动的把字符串 “:joy:” 渲染上去了。
所以该怎么办?提供几种思路:

更改 Markdown 渲染引擎

Hexo 的渲染引擎是 Marked,Hexo3.0 版本的渲染引擎也支持 GitHub Flavored。我查阅了网上很多的支持 Emoji 的开源的 Markdown 引擎,确实找到了一些比如 Markdown Editor,不够后来我才发现,这些引擎或多或少都是在很多官方引擎的基础上加入了自己的拓展功能,才实现了能够渲染 Emoji。不过 Hexo 不能随意的将默认渲染引擎切换到这些第三方渲染引擎中来,顶多就是开启或者关闭一下 GitHub Flavored。此路不通,换一条路。

找相关的 Hexo 插件

打开 Hexo 的 Issue,搜索 Emoji:

搜到上面的这么少的结果,我的内心是崩溃的,T T,打开之后,就了解到了 hexo-tag-emojis,按照官方的文档装完之后,各种问题。后来查了这个插件的 Issue 才知道,这个插件已经不能友好支持 Hexo3.0 以上版本了。但是我按照 Issue 里支持 Hexo3.0 的用法用,依然出现各种问题。我提了一个 Issue 上去,估计作者也不会理吧,毕竟很久没更了。不过还好,用了这个插件之后,会把 emoji 的大部分 PNG 图片都安装到 source 目录下的 /images/Emojis

自己想办法搞定

这真的是不得已而为之方法,xxx教导我们:

不要重复造轮子!
不要重复造轮子!
不要重复造轮子!

这些年就是靠着这些(jie)话(kou),导致我一步一步成为搬砖的民工(脸红)。
那就从上面提到的 hexo-tag-emojis 开始下手吧,其实这个插件比较简单,只有一个index.js,里面注册了两个标签,选一个 emoji 标签看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
hexo.extend.tag.register('emoji', function(args, content){
var emojiName = args[0]; // emojiNameWithoutColons argument
var emojiSize = args[1] || defaultEmojiSize;
var classes = args[2] || "";
var imgAttr = {};
if (!emojiConfig || !emojiPrefix) {
throw new Error('Emoji configuration was not found.');
}
classes = classes.split(',');
classes.push('emoji');
classes.push('nofancybox');
imgAttr.src = emojiPrefix +'/'+emojiName+'.png';
imgAttr.width = emojiSize;
imgAttr.height = emojiSize;
imgAttr.class = classes.join(' ');
imgAttr.title = emojiName;
return htmlTag('img', imgAttr);
});

上面这段代码的目的只有一个,就是让 Hexo 能够识别你在 Markdown 文件里写

1
{ % emoji arg0 arg1 ... % } 注:( { 和 % 之间是没有空格的)

然后获取相应的参数来返回特定的 HTML 标签。实际上就是一个 IMG 标签嘛!但是不知道为何,里面的 emoji 类和 nofancybox 类貌似在 Hexo3.0 版本里失效了,不知道是因为 NexT 主题的冲突还是什么原因。我直接在 Markdown 里写:

1
<img src="/images/emojis/joy.png" class="emoji nofancybox" />

发现并没有什么卵用,样式没有改变。后来参考了NextT主题自己的full-image的写法,在 NexT 主题的source\css\_common\components\tags\目录下写了一个emoji-image样式:

1
2
3
4
.emoji-image.emoji-image.emoji-image{
border: none;
float: left; //为什么要float: left?后面解释
}

然后写了函数一个注册了一下标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function emojiImage(args) {
args = args.join(' ').split(',');
var src = args[0];
var size = args[1] || '';
var title = args[2] || '';
if (!src) {
hexo.log.warn('Image src can NOT be empty');
}
size = size.trim();
title = title.trim();
var image = ['<img src="/images/emojis/' + src + '.png" class="emoji-image"'];
size.length > 0 && image.push('width="' + size + 'px"');
title.length > 0 && image.push('title="' + title + '"');
image.push('/>');
return image.join(' ');
}
hexo.extend.tag.register('emojiImage', emojiImage);
hexo.extend.tag.register('ei', emojiImage);

这样的话,只要在 Mardown 文件里写 { % ei emojiName size % } 就可以转换成对应尺寸的 Emoji 表情。
比如我写

1
{ % ei cry,32 % } 注:( { 和 % 之间是没有空格的)

显示:

问题

使用这样的方式插入 Emoji 表情,在 fancybox 效果(可以点击图片,出现模态框来浏览图片)默认开启的情况下,只能插入一行文字的最左侧。
其实最好的方式是能插在一句话的任何地方:比如Hello,[emoji]Hexo!但前提是你要把 NextT 主题配置文件的fancybox: true改为false,然后把 emoji-image 样式中的float: left 去掉就ok了。
对于一个强迫症的我来说,我还是比较喜欢fancybox的效果的,不忍心为了能在任何地方插入 Emoji,就关闭fancybox的效果。
所以终极的解决方案是:

能够控制每一张图片是否自带 fancybox 效果,把是 Emoji 的图片 fancybox 的效果去掉,其他图片保留。

我想 hexo-tags-emojis 作者的 nofancybox 类也是想实现这个效果,但不知为何失效。
我在 NexT 主题下提了一个 Issue,实现能够在一行文字之间插入图片也是可以的,这样也不仅仅局限于只能插入 Emoji 表情了。

就酱,生命不息,折腾不止。