-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Description
Describe the bug
If I have such a sidebar config object:
{
"/a": [
{
"text": "a copy",
"link": "/a/a-copy",
"collapsed": true,
"items": [
{
"text": "Runtime API Examples",
"link": "/a/a-copy/api-examples.md",
".sort_base": "api-examples.md"
},
{
"text": "Markdown Extension Examples",
"link": "/a/a-copy/markdown-examples.md",
".sort_base": "markdown-examples.md"
}
],
".sort_base": "a-copy"
},
{
"text": "📂 b-copy",
"collapsed": true,
"items": [
{
"text": "Markdown Extension Examples",
"link": "/a/b-copy/markdown-examples.md",
".sort_base": "markdown-examples.md"
},
{
"text": "Runtime API Examples",
"link": "/a/b-copy/z_api-examples.md",
".sort_base": "z_api-examples.md"
}
],
".sort_base": "b-copy"
}
],
"/": [
{
"text": "Runtime API Examples",
"link": "/api-examples.md",
".sort_base": "api-examples.md"
},
{
"text": "Markdown Extension Examples",
"link": "/markdown-examples.md",
".sort_base": "markdown-examples.md"
},
{
"text": "a",
"link": "/a",
"collapsed": true,
"items": [
{
"text": "a copy",
"link": "/a/a-copy",
"collapsed": true,
"items": [
{
"text": "Runtime API Examples",
"link": "/a/a-copy/api-examples.md",
".sort_base": "api-examples.md"
},
{
"text": "Markdown Extension Examples",
"link": "/a/a-copy/markdown-examples.md",
".sort_base": "markdown-examples.md"
}
],
".sort_base": "a-copy"
},
{
"text": "📂 b-copy",
"collapsed": true,
"items": [
{
"text": "Markdown Extension Examples",
"link": "/a/b-copy/markdown-examples.md",
".sort_base": "markdown-examples.md"
},
{
"text": "Runtime API Examples",
"link": "/a/b-copy/z_api-examples.md",
".sort_base": "z_api-examples.md"
}
],
".sort_base": "b-copy"
}
],
".sort_base": "a"
}
]
}
when I access path "/api-examples.md", it will decide the sidebar to "/a", just because "/api-examples.md" starts with "/a".
Reproduction
Clone my repo, run
pnpm i
and
pnpm run dev
go to "http:///markdown-examples.html"
you will see the sidebar is good right now.
and click the Runtime API Examples, boomb💥 the sidebar which belongs to "/" disappeared.
Expected behavior
I expect that when i access path /api-examples.html
, the sidebar remains same as when I access /markdown-examples.html
.
System Info
$ npx envinfo --system --npmPackages vitepress --binaries --browsers
Need to install the following packages:
[email protected]
Ok to proceed? (y) y
System:
OS: Windows 11 10.0.26100
CPU: (16) x64 AMD Ryzen 7 8845H w/ Radeon 780M Graphics
Memory: 6.63 GB / 31.29 GB
Binaries:
Node: 23.7.0 - C:\nvm4w\nodejs\node.EXE
Yarn: 1.22.22 - C:\nvm4w\nodejs\yarn.CMD
npm: 10.9.2 - C:\nvm4w\nodejs\npm.CMD
pnpm: 10.9.0 - C:\nvm4w\nodejs\pnpm.CMD
Browsers:
Edge: Chromium (138.0.3351.55)
npmPackages:
vitepress: ^1.6.3 => 1.6.3
Additional context
Tried to figure out the cause in vitepress sourcecode, and I think the function getSidebar
in src\client\theme-default\support\sidebar.ts
is buggy, it shouldn't just only check the starting chararcters of the path
, should also to check the remaining part after the same starting string...
/**
* Get the `Sidebar` from sidebar option. This method will ensure to get correct
* sidebar config from `MultiSideBarConfig` with various path combinations such
* as matching `guide/` and `/guide/`. If no matching config was found, it will
* return empty array.
*/
export function getSidebar(
_sidebar: DefaultTheme.Sidebar | undefined,
path: string
): SidebarItem[] {
if (Array.isArray(_sidebar)) return addBase(_sidebar)
if (_sidebar == null) return []
path = ensureStartingSlash(path)
const dir = Object.keys(_sidebar)
.sort((a, b) => {
return b.split('/').length - a.split('/').length
})
.find((dir) => {
// make sure the multi sidebar key starts with slash too
return path.startsWith(ensureStartingSlash(dir))
})
const sidebar = dir ? _sidebar[dir] : []
return Array.isArray(sidebar)
? addBase(sidebar)
: addBase(sidebar.items, sidebar.base)
}
Thinking it will work this way:
/**
* Get the `Sidebar` from sidebar option. This method will ensure to get correct
* sidebar config from `MultiSideBarConfig` with various path combinations such
* as matching `guide/` and `/guide/`. If no matching config was found, it will
* return empty array.
*/
export function getSidebar(
_sidebar: DefaultTheme.Sidebar | undefined,
path: string
): SidebarItem[] {
if (Array.isArray(_sidebar)) return addBase(_sidebar)
if (_sidebar == null) return []
path = ensureStartingSlash(path)
const dir = Object.keys(_sidebar)
.sort((a, b) => {
// longer dir link has higher priority
return b.split('/').length - a.split('/').length
})
.find((dir) => {
const dirWithStartingSlash = ensureStartingSlash(dir)
// make sure the multi sidebar key starts with slash too
if (path.startsWith(dirWithStartingSlash)) {
// "/" match everything and it has lowest priority
if (dirWithStartingSlash === '/') return true
const remains = path.replace(dirWithStartingSlash, '')
if (remains.startsWith('/') || remains === '') return true
}
})
const sidebar = dir ? _sidebar[dir] : []
return Array.isArray(sidebar)
? addBase(sidebar)
: addBase(sidebar.items, sidebar.base)
}
Validations
- Check if you're on the latest VitePress version.
- Follow our Code of Conduct
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.