本文不涉及对主题源代码的修改

今天又开一个坑,写了一个插件方便我自定义链接的样式。按照以往惯例我可能又得写一小篇开发心得 ,不过这次我打算以「Q&A」的方式将一些思考放在文章末尾。

一般来说,改变链接样式似乎写个全局 CSS 就行,但如果实现复杂效果,比如在链接附近加上 span 标签等等的实现可能会有所复杂。我暂时想到的解决方案就是从 Markdown 文本上替换超链接,使用指定 HTML 模板,与是就试着写了这样一个插件。

结果写完后发现他还有一个意料之外的功能,就是它可以实现和一些标签插件一样的效果,这就可以把部分文章内的 Hexo 标签语法给省略掉了。如果有一天你切换到其他不支持标签语法的博客,你的网页就不会遗留下诸如 {% name param1 param2 strange_string magic_number%} 之类的东西。

这篇文章主要内容为使用 hexo-filter-custom-link 插件对超链接进行美化的案例,如增加链接悬浮效果等。本文算是对这个插件的小小入门,更多替换标签语法的操作详看:站内文章用 Markdown 链接替换部分 Hexo 标签语法

gif

hexo-filter-custom-link 插件为涉及到文章「超链接」的主题魔改增加了一种新的选择。而且以后在对超链接美化时,我们可以:

  • 尽可能避免主题的源代码修改;
  • 尽可能少用 Hexo 内置的标签语法,减少文章维护成本。

插件安装与使用

安装与使用方式见项目 README 文档。

Readme Card

GitHub 项目地址:uuanqin/hexo-filter-custom-link: Customize the rendered HTML of Links. 自定义链接渲染后的 HTML

主要功能:

  • 自定义链接渲染后的样式,让形如 [text](url)[text](url "title") 的超链接渲染成你想要的模板。
  • 插件提供多种通配符方便设计更复杂的模板,通配符可以重复使用。
  • 在特殊情况下,可以为一些特殊链接指定不同的模板,让超链接的样式更加丰富。
  • 对于复杂模板,支持模板间距以区分其他 Markdown 文本,避免渲染错误。

插件原理是在 Markdown 文本编译前,识别链接形式并进行模板替换的。目前测试了该插件与以下「链接替换」插件(毕竟博主还在用…)并不冲突:

为普通链接增加悬浮样式

本小节含三个案例,均基于 Codepen 项目简化处理。如果想实现原版效果可到原项目中查看具体代码。

例 1:鼠标悬浮色块聚焦

本案例基于该项目进行简化:Awesome link underlines

最简单的入门案例。

demo

_config.yml 配置如下:

1
2
3
custom_link:  
enable: true # enable this plugin
general_template: '<a class="link-example-1" href="__URL__">__TEXT__</a>'

引入以下 CSS 即可:

1
2
3
4
5
6
7
8
9
10
11
12
.link-example-1 {
color: black;
border-bottom: 0.1em solid #669900;
outline: 1em solid rgba(255, 215, 0, 0);
text-decoration: none;
transition: all 0.3s ease;
}

.link-example-1:hover, .link-example-1:focus, .link-example-1:active {
background: #b5ca4226;
outline: 0.1em solid #b5ca4226;
}

实际上插件做的就是把每个链接加上 .link-example-1 类,我们通过自定义 CSS 就能调整链接的样式。更多炫酷效果可到原项目查看。

这个项目是 站内文章很久以前 使用过的,算是从垃圾桶捡回来举例了😂

例 2:鼠标悬浮小弹窗

本案例基于该项目进行简化:Best Creative Link Hover

gif

_config.yml 配置如下:

1
2
3
4
5
6
custom_link:
enable: true # enable this plugin
general_template: |
<a class="link-example-2" href="__URL__">
<span class="pop-up">弹窗</span>
__TEXT__</a>

引入以下 CSS 文件:

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
/*https://codepen.io/ysoftaoglu/pen/JXROeY*/

.link-example-2 {
display: inline-block;
transition: all .2s ease;
}

span.pop-up {
display: block;
/* font-size: 21px; */
font-weight: normal;
/*transform: translateY(20px);*/
transition: all .2s ease;
opacity: 0;
position: absolute; /* 将 span 绝对定位 */
top: 0;
left: 50%; /* 水平居中 */
transform: translate(-50%, -80%); /* 调整位置使其完全居中 */
width: auto; /* 设置宽度为0,使其不占空间 */
height: auto; /* 设置高度为0,使其不占空间 */
white-space: nowrap; /* 文字不折叠 */
font-size: 12px; /* 固定文字大小 */
font-style: normal; /* 设置正斜体 */
border-radius: 10px;
padding: 0px 8px;
background-color: #c7046f;
color: #fff;
}

.link-example-2:hover span.pop-up,
.link-example-2:focus span.pop-up {
opacity: 1;
}

.link-example-2:hover {
transform: translateY(-2px);
text-decoration: none !important;
}

针对本案例,以上面的方式配置的话在大多数情况下小弹窗能正常显示,但是有可能被部分表格顶部覆盖。我们可以添加以下 JavaScript 以更好解决这个问题:

1
2
3
4
5
6
7
8
9
10
// 用于解决遮挡问题
document.addEventListener('DOMContentLoaded', function() {
const aclassElements = document.querySelectorAll('.table-wrap');
aclassElements.forEach(function(tableWrapElement) {
if (tableWrapElement.querySelector('span.pop-up')) {
// 如果包含,则设置 overflow: visible;
tableWrapElement.style.overflow = 'visible';
}
});
});
这个链接气泡好像有点眼熟?

这是目前本站双向链接的效果,和本站 站内文章评论区悬浮气泡 效果恰好统一。(此处暗示了读者去评论区评论试试气泡效果😉)

例 3:鼠标悬浮变动下划线

本案例基于该项目进行简化:Link Hover Flash

img

本例和例 1 相似,只需要为链接加上类即可。

_config.yml 配置如下:

1
2
3
custom_link:
enable: true # enable this plugin
general_template: '<a class="link-example-3" href="__URL__">__TEXT__</a>'

引入以下 CSS 文件:

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
/*https://codepen.io/alphardex/details/WNQPWmj*/

.link-example-3 {
--ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
position: relative;
}
.link-example-3::before, .link-example-3::after {
position: absolute;
content: "";
left: 0;
bottom: -2px;
display: block;
width: 100%;
height: 3px;
background: #dcb438;
transition: 1.1s var(--ease-out-expo);
}
.link-example-3::before {
transform: scaleX(0);
transform-origin: left;
}
.link-example-3::after {
transform-origin: right;
transition-delay: 0.25s;
}
.link-example-3:hover::before {
transform: scaleX(1);
transition-delay: 0.25s;
}
.link-example-3:hover::after {
transform: scaleX(0);
transition-delay: 0s;
}

后记

插件一边写一边增加新的功能,时间都花在找 Bug 上!

写插件的小小心得

为什么博主执着于避免修改主题源码以及摒弃标签语法这两点?

自从博主使用 Hexo 以来,在对博客的美化道路就十分坎坷。我总是小心翼翼地避开对 Butterfly 源代码的修改,其中一个原因就是认为改了代码后 Git 维护变繁杂了且主题不好升级。(但实际上为了小破站安全,博主最终还是 站内文章迫不得已 改了一些源代码去掉了敏感外链,这也直接导致我需要维护新的分支)

至于 Hexo 的标签语法博主是坚决不使用的。标签语法强依赖于 Hexo 或某一个 Hexo 插件。如果博客更换为其他项目,文章中会遗留许多奇奇怪怪的特殊标记。另外,目前文章使用了 GFM、OFM 语法,花了很大的精力维护了 Hexo 和 Obsidian 站内文章两端的统一。为了以后文字长久的兼容性,真的真的不能再用任何新语法了。

一句话总结:博主有非常奇怪的「洁癖」😰。

这个插件是如何诞生的?

本小站是通过 站内文章Obsidian 进行维护的。很久以前在到处 站内文章玩插件时 就有一个想法,就是打算为站内的双向链接做出不一样的标识以在 Hexo 发挥双链的优势。于是我改进了以前写过的双链插件 hexo-filter-titlebased-link 使其支持自定义渲染后的链接形式实现小弹窗效果。后来发现这部分功能可以是通用的,不如将它提取出来使之能应用到更多的链接形式中。

这个插件和魔改源代码又有什么区别?

插件原理和魔改主题源代码基本相同。插件只是用更无痛的「配置」方式代替了源码修改操作。当然使用插件也是有缺点的,首先就是灵活度受限,其次就是依赖性了。

这个插件和标签语法又有什么区别?

可以说插件把 丑陋 的标签语法变「漂亮」了,但有可能没有标签语法那么灵活。这个插件可以使用自定义占位符满足一部分的标签语法场景。

插件是不是使用了新的标记语言,这是否与前面不使用新语法的观点相悖?

特殊链接是需要特征的,「标记」无可避免。但是插件不引入新语法,它只是将标记放置于链接标题中 [name](url "title")"title" 这个位置十分隐蔽,之前我都没注意到 Markdown 还有这个语法,估计也没多少人用)。链接标题一般只有在鼠标悬浮在链接时才会展现,即使卸载本插件,原文章的页面展示上还是一个普通的超链接,不会增加奇奇怪怪的内容。

往期心得:

后续任务

  • 顺便把 hexo-filter-titlebased-link 插件也升级一下
  • 疑似 hexo 渲染插件的 Bug,待排查。目前推测为 mdit-plugin-callouts 的 Bug。
  • 取消 %% 标签,把参数放到 TITLE 中

参考文章

工具:

样板代码参考:

其他: