bug解决——hexo插件冲突导致tocbot生成目录跳转异常

本文最后更新于:1 分钟前

问题说明

在使用hexo部署博客时,使用了fluid主题,该主题可以使用tocbot在右侧生成一个跳转的目录,如下:

image-20240716091527332

为了使用更强的markdown渲染器,选择将hexo默认markdown渲染器的hexo-renderer-marked卸载,转而安装hexo-renderer-markdown-it,该渲染器支持在**<hi>标签上自动生成标题锚点,并自动生成标题id**,该标题id即可用于tocbot自动扫描,并为右侧的目录生成跳转链接,保证右侧目录的正确跳转

但为了在文章正文中插入目录(一般是开头),需要其他的插件的支持,考虑到markdown-it-toc-and-anchor现在已不再维护,其使用的markdown-it版本太低,故添加插件hexo-toc用于生成标题锚点和文章目录(标题锚点请在hexo-renderer-markdown-it和hexo-toc中二选一),该插件只需要在markdown文章中任意位置添加**<div class="tocStart">

**即可生成目录

但是,同时使用二者导致了一个特殊的bug,即右侧的tocbot目录的跳转只能回到文章页面的顶部,无法正确跳转到标题位置,通过浏览器的F12检查得知了其原因:

image-20240716092938088

image-20240716092903108

这里可以看到,<h3>目录并未像预期的那样生成id,而是添加了一个**<span>**标签,并在其中生成了标题id,这使得tocbot的扫描结果变成了如下的情况:

image-20240716093158727

通过标题跳转的超链接标签<a title>中的href=“#”可知,tocbot生成的标题超链接只能回滚到页面顶部,无法跳转到指定的目录标题位置,而这正是因为标题id位于<span>标签,无法被tocbot获得所导致的,此时,只能通过tocbot中的标题锚点,即“¶”完成正确跳转

如果需要tocbot正常工作,标题处的html结构和tocbot的html结构应如下

image-20240716094617125

image-20240716094654457

观察可知,在<h3>标签中生成了标题的id,而不是在一个span标签中,进而tocbot在扫描后可以在自动目录中正确生成对应的href链接,指向该标题id,此时的点击应能正确跳转

问题解决

在本人尝试了多种方法后,最终在github的issue区Content's link show 'undefine' · Issue #11 · YenYuHsuan/hexo-theme-beantech (github.com)中,看到了**fawks96**这位大佬的回复,并以此解决了问题:

image-20240716094108934

这里的代码位于博客目录下的node_modules\hexo-toc\lib\filter.js文件内,打开后如下:

image-20240716094343221

代码说明如下

1
2
3
4
5
6
7
8
9
// 为$title元素设置一个id属性,属性值为变量id的值。
$title.attr('id', id);

// 移除标题元素$title下的所有直接子元素中的<a>标签,即:如果标题元素$title的子元素中包含<a>标签,这些<a>标签会被从html结构中移除
$title.children('a').remove();
// 将标题元素$title 的HTML内容包裹在一个<span>元素内,并设置这个 <span> 元素的 id 属性为变量id的值
$title.html( '<span id="' + id + '">' + $title.html() + '</span>' );
// 移除标题元素$title上的id属性
$title.removeAttr('id');

从这里可以看出,hexo-toc在更新后直接移除了标题中的id和子元素中的超链接,改为添加<span>标签,这里没有考虑其他插件的工作过程和效果,因此最终导致了问题的发生

解决方法也很简单,直接修改源码(回滚版本),即可:

image-20240716100825645

重新部署,可以看到其效果如上面的正确结构所示,且所有跳转均恢复正常

最后,附上我个人Blog中的**_config.ymlhexo-renderer-markdown-ithexo-toc**配置:

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
# hexo-toc config—— by <!-- toc --> to insert toc
toc:
maxdepth: 6
class: toc
slugify: usluq
decodeEntities: false
anchor:
position: before
symbol: '¶'
style: header-anchor

# Markdown renderer config —— using hexo-renderer-markdown-it-plus
markdown:
preset: "default"
render:
html: true
xhtmlOut: false
langPrefix: "language-"
breaks: false
linkify: true
typographer: false
quotes: '“”‘’'
enable_rules:
disable_rules:
plugins:
- markdown-it-emoji # 表情
- markdown-it-footnote # 脚注(参考文献)
- markdown-it-abbr # 支持<abbr>标签缩写
- markdown-it-cjk-breaks # 移除不符合规范的单换行
# - markdown-it-deflist # 支持将markdown定义列表
- markdown-it-sup # 上标
- markdown-it-sub # 下标
- markdown-it-ins # 下划线和中划线(就是划掉指定内容的线)
- markdown-it-mark # 高亮文本
- markdown-it-checkbox # 复选框
- markdown-it-imsize # 自定义图片宽高
- markdown-it-expandable # 折叠/展开内容
- markdown-it-task-lists # 处理任务列表语法(GFM可使用Todo list)
anchors:
level: 1 # 用2时一级标题无法跳转,建议打开
collisionSuffix: ''
permalink: false # 取消permalink,使用toc即可,或者也可以toc后不添加任何内容,使用permalink: true
permalinkClass: 'header-anchor'
permalinkSide: 'left'
permalinkSymbol: '¶'
case: 0
separator: '-'

如果同样使用fluid主题的话,注意主题配置文件**_config.ymlanchorjs**需要关闭:

1
2
3
4
5
6
7
8
9
10
11
# 为文章内容中的标题添加锚图标,此处需要关系
# Add an anchor icon to the title on the post page
anchorjs:
enable: false
element: h1,h2,h3,h4,h5,h6
# Options: left | right
placement: left
# Options: hover | always | touch
visible: always
# Options: § | # | ❡
icon: "❡"