From 610cc17af0624d82d0eb3ed652f0b5fa1c2402f0 Mon Sep 17 00:00:00 2001 From: Kia King Ishii Date: Sat, 5 Sep 2020 19:25:55 +0900 Subject: [PATCH] fix: sidebar not working correctly when path starts with slash It fixes the problems that: 1. When base url and sidebar link url join problem. 2. Sidebat headings without a link is marked as "active". --- src/client/theme-default/components/SideBar.ts | 8 ++++++-- src/client/theme-default/utils.ts | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/client/theme-default/components/SideBar.ts b/src/client/theme-default/components/SideBar.ts index 8a8b677c..89988165 100644 --- a/src/client/theme-default/components/SideBar.ts +++ b/src/client/theme-default/components/SideBar.ts @@ -6,7 +6,7 @@ import { } from 'vitepress' import { computed, h, FunctionalComponent, VNode } from 'vue' import { Header } from '../../../../types/shared' -import { isActive, getPathDirName } from '../utils' +import { isActive, joinUrl, getPathDirName } from '../utils' import { DefaultTheme } from '../config' import { useActiveSidebarLinks } from '../composables/activeSidebarLink' @@ -21,7 +21,7 @@ const SideBarItem: FunctionalComponent<{ const pageData = usePageData() const siteData = useSiteData() - const link = `${siteData.value.base}${relLink || ''}` + const link = resolveLink(siteData.value.base, relLink || '') const active = isActive(route, link) const headers = pageData.value.headers @@ -150,6 +150,10 @@ function resolveMultiSidebar( return [] } +function resolveLink(base: string, path: string): string | undefined { + return path ? joinUrl(base, path || '') : undefined +} + function createLink(active: boolean, text: string, link?: string): VNode { const tag = link ? 'a' : 'p' diff --git a/src/client/theme-default/utils.ts b/src/client/theme-default/utils.ts index 25d6580a..b2ff533e 100644 --- a/src/client/theme-default/utils.ts +++ b/src/client/theme-default/utils.ts @@ -27,6 +27,21 @@ export function normalize(path: string): string { return decodeURI(path).replace(hashRE, '').replace(extRE, '') } +export function joinUrl(base: string, path: string): string { + const baseEndsWithSlash = base.endsWith('/') + const pathStartsWithSlash = path.startsWith('/') + + if (baseEndsWithSlash && pathStartsWithSlash) { + return base.slice(0, -1) + path + } + + if (!baseEndsWithSlash && !pathStartsWithSlash) { + return `${base}/${path}` + } + + return base + path +} + /** * get the path without filename (the last segment). for example, if the given * path is `/guide/getting-started.html`, this method will return `/guide/`.