正则表达式匹配导致VitePress导航栏被错误地高亮(已修复)
刚才遇到了VitePress默认主题的导航栏有时会错误地高亮的问题,在此记录一下。
提示
目前该BUG已被修复。
发现问题
原先我的导航栏配置大概长这样:
nav: [
{
text: "MC",
activeMatch: "/minecraft/",
items: [
{ text: "板块简介", link: "/minecraft/" },
{ text: "工具软件", link: "/minecraft/software/mspm-old" },
],
},
{
text: "软件",
activeMatch: "/software/",
items: [
{ text: "板块简介", link: "/software/" },
{ text: "实用工具", link: "/software/utility/alpha-pixel-image" },
{ text: "FUN", link: "/software/fun/boids-test" },
],
},
];2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
很快我发现一个问题,就是在/minecraft/software/mspm-old页面下,导航栏内的MC和软件两项都会被高亮显示。
再次阅读官方文档后,我才意识到,原来这个activeMatch字段是一个正则表达式,而/minecraft/software/mspm-old这个路径同时匹配了/minecraft/和/software/两个正则表达式,于是导航栏内的两项同时都被高亮了。
解决办法显而易见,就是修改activeMatch字段,让它只匹配字符串的开头就好了。
nav: [
{
text: "MC",
activeMatch: "^/minecraft/",
items: [
{ text: "板块简介", link: "/minecraft/" },
{ text: "工具软件", link: "/minecraft/software/mspm-old" },
],
},
{
text: "软件",
activeMatch: "^/software/",
items: [
{ text: "板块简介", link: "/software/" },
{ text: "实用工具", link: "/software/utility/alpha-pixel-image" },
{ text: "FUN", link: "/software/fun/boids-test" },
],
},
];2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
发现BUG
使用正则表达式后,上述问题依然存在,排查过后发现是VitePress的相关代码出了问题。
需要说明的是,VitePress有一个特性,就是当导航栏列表组内的任何一项被匹配并高亮时,该列表组的标题总是会高亮。
列表项自身的高亮代码并没有毛病,然而在列表组标题判断它的子项是否被高亮时,这里出了点岔子。
原先的相关代码如下:
const isChildActive = (navItem: DefaultTheme.NavItem) => {
if ('component' in navItem) return false
if ('link' in navItem) {
return isActive(
page.value.relativePath,
typeof navItem.link === "function" ? navItem.link(page.value) : navItem.link,
!!props.item.activeMatch
)
}
return navItem.items.some(isChildActive)
}2
3
4
5
6
7
8
9
10
11
12
13
其中,props.item是包含列表标题的导航栏列表组,navItem是列表组内的一个列表项。
isActive函数定义如下:
export function isActive(
currentPath: string,
matchPath?: string,
asRegex: boolean = false
): boolean { ... }2
3
4
5
可以发现,当列表组使用正则表达式时即!!props.item.activeMatch为true时,它在遍历自己的子项时,会错误地把子项的link字段当作正则表达式去匹配当前页面的相对路径,不论那个子项是否启用了正则表达式。
修复BUG
要修复的话,在调用isActive函数时判断一下每一个子项是否启用了正则表达式就好。
const isChildActive = (navItem: DefaultTheme.NavItem) => {
if ('component' in navItem) return false
if ('link' in navItem) {
return isActive(
page.value.relativePath,
typeof navItem.link === "function" ? navItem.link(page.value) : navItem.link,
!!props.item.activeMatch
navItem.activeMatch ? navItem.activeMatch : (typeof navItem.link === "function" ? navItem.link(page.value) : navItem.link),
!!navItem.activeMatch
)
}
return navItem.items.some(isChildActive)
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
应对方法
等待更新
目前,修复该BUG的相关PR已被合并,等到VitePress下个版本发布就好。
目前该BUG已被修复。
缓兵之计
使用patch-package为你的node_modules打补丁,无需等待VitePress更新。