From 9a4ee07260191adeb4c3810d95b044439609525c Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Tue, 8 Aug 2023 20:39:49 +0530 Subject: [PATCH] fix(theme): fix sidebar collapsing and restore base property (#2753) --- docs/.vitepress/config.ts | 74 +++++++++---------- .../theme-default/composables/sidebar.ts | 19 +++-- src/client/theme-default/support/sidebar.ts | 17 ++++- types/default-theme.d.ts | 7 +- 4 files changed, 67 insertions(+), 50 deletions(-) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 43f6b9cc..0bbeef1b 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -53,8 +53,8 @@ export default defineConfig({ nav: nav(), sidebar: { - '/guide/': sidebarGuide(), - '/reference/': sidebarReference() + '/guide/': { base: '/guide/', items: sidebarGuide() }, + '/reference/': { base: '/reference/', items: sidebarReference() } }, editLink: { @@ -122,72 +122,72 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] { text: 'Introduction', collapsed: false, items: [ - { text: 'What is VitePress?', link: '/guide/what-is-vitepress' }, - { text: 'Getting Started', link: '/guide/getting-started' }, - { text: 'Routing', link: '/guide/routing' }, - { text: 'Deploy', link: '/guide/deploy' } + { text: 'What is VitePress?', link: 'what-is-vitepress' }, + { text: 'Getting Started', link: 'getting-started' }, + { text: 'Routing', link: 'routing' }, + { text: 'Deploy', link: 'deploy' } ] }, { text: 'Writing', collapsed: false, items: [ - { text: 'Markdown Extensions', link: '/guide/markdown' }, - { text: 'Asset Handling', link: '/guide/asset-handling' }, - { text: 'Frontmatter', link: '/guide/frontmatter' }, - { text: 'Using Vue in Markdown', link: '/guide/using-vue' }, - { text: 'Internationalization', link: '/guide/i18n' } + { text: 'Markdown Extensions', link: 'markdown' }, + { text: 'Asset Handling', link: 'asset-handling' }, + { text: 'Frontmatter', link: 'frontmatter' }, + { text: 'Using Vue in Markdown', link: 'using-vue' }, + { text: 'Internationalization', link: 'i18n' } ] }, { text: 'Customization', collapsed: false, items: [ - { text: 'Using a Custom Theme', link: '/guide/custom-theme' }, - { text: 'Extending the Default Theme', link: '/guide/extending-default-theme' }, - { text: 'Build-Time Data Loading', link: '/guide/data-loading' }, - { text: 'SSR Compatibility', link: '/guide/ssr-compat' }, - { text: 'Connecting to a CMS', link: '/guide/cms' } + { text: 'Using a Custom Theme', link: 'custom-theme' }, + { text: 'Extending the Default Theme', link: 'extending-default-theme' }, + { text: 'Build-Time Data Loading', link: 'data-loading' }, + { text: 'SSR Compatibility', link: 'ssr-compat' }, + { text: 'Connecting to a CMS', link: 'cms' } ] }, { text: 'Experimental', collapsed: false, items: [ - { text: 'MPA Mode', link: '/guide/mpa-mode' }, - { text: 'Sitemap Generation', link: '/guide/sitemap-generation' } + { text: 'MPA Mode', link: 'mpa-mode' }, + { text: 'Sitemap Generation', link: 'sitemap-generation' } ] }, - { text: 'Config & API Reference', link: '/reference/site-config' } + { text: 'Config & API Reference', base: '/reference/', link: 'site-config' } ] } -/* prettier-ignore */ function sidebarReference(): DefaultTheme.SidebarItem[] { return [ { text: 'Reference', items: [ - { text: 'Site Config', link: '/reference/site-config' }, - { text: 'Frontmatter Config', link: '/reference/frontmatter-config' }, - { text: 'Runtime API', link: '/reference/runtime-api' }, - { text: 'CLI', link: '/reference/cli' }, + { text: 'Site Config', link: 'site-config' }, + { text: 'Frontmatter Config', link: 'frontmatter-config' }, + { text: 'Runtime API', link: 'runtime-api' }, + { text: 'CLI', link: 'cli' }, { text: 'Default Theme', + base: '/reference/default-theme-', items: [ - { text: 'Overview', link: '/reference/default-theme-config' }, - { text: 'Nav', link: '/reference/default-theme-nav' }, - { text: 'Sidebar', link: '/reference/default-theme-sidebar' }, - { text: 'Home Page', link: '/reference/default-theme-home-page' }, - { text: 'Footer', link: '/reference/default-theme-footer' }, - { text: 'Layout', link: '/reference/default-theme-layout' }, - { text: 'Badge', link: '/reference/default-theme-badge' }, - { text: 'Team Page', link: '/reference/default-theme-team-page' }, - { text: 'Prev / Next Links', link: '/reference/default-theme-prev-next-links' }, - { text: 'Edit Link', link: '/reference/default-theme-edit-link' }, - { text: 'Last Updated Timestamp', link: '/reference/default-theme-last-updated' }, - { text: 'Search', link: '/reference/default-theme-search' }, - { text: 'Carbon Ads', link: '/reference/default-theme-carbon-ads' } + { text: 'Overview', link: 'config' }, + { text: 'Nav', link: 'nav' }, + { text: 'Sidebar', link: 'sidebar' }, + { text: 'Home Page', link: 'home-page' }, + { text: 'Footer', link: 'footer' }, + { text: 'Layout', link: 'layout' }, + { text: 'Badge', link: 'badge' }, + { text: 'Team Page', link: 'team-page' }, + { text: 'Prev / Next Links', link: 'prev-next-links' }, + { text: 'Edit Link', link: 'edit-link' }, + { text: 'Last Updated Timestamp', link: 'last-updated' }, + { text: 'Search', link: 'search' }, + { text: 'Carbon Ads', link: 'carbon-ads' } ] } ] diff --git a/src/client/theme-default/composables/sidebar.ts b/src/client/theme-default/composables/sidebar.ts index c18a28dd..4d98edfc 100644 --- a/src/client/theme-default/composables/sidebar.ts +++ b/src/client/theme-default/composables/sidebar.ts @@ -1,16 +1,16 @@ +import { useMediaQuery } from '@vueuse/core' +import type { DefaultTheme } from 'vitepress/theme' import { - type ComputedRef, - type Ref, computed, onMounted, onUnmounted, ref, + watch, watchEffect, - watch + watchPostEffect, + type ComputedRef, + type Ref } from 'vue' -import { useMediaQuery } from '@vueuse/core' -import { useRoute } from 'vitepress' -import type { DefaultTheme } from 'vitepress/theme' import { inBrowser, isActive } from '../../shared' import { hasActiveLink as containsActiveLink, @@ -30,15 +30,14 @@ export interface SidebarControl { } export function useSidebar() { - const route = useRoute() - const { theme, frontmatter } = useData() + const { frontmatter, page, theme } = useData() const is960 = useMediaQuery('(min-width: 960px)') const isOpen = ref(false) const sidebar = computed(() => { const sidebarConfig = theme.value.sidebar - const relativePath = route.data.relativePath + const relativePath = page.value.relativePath return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : [] }) @@ -176,7 +175,7 @@ export function useSidebarControl( collapsed.value = !!(collapsible.value && item.value.collapsed) }) - watchEffect(() => { + watchPostEffect(() => { ;(isActiveLink.value || hasActiveLink.value) && (collapsed.value = false) }) diff --git a/src/client/theme-default/support/sidebar.ts b/src/client/theme-default/support/sidebar.ts index 6385c55e..955eb23e 100644 --- a/src/client/theme-default/support/sidebar.ts +++ b/src/client/theme-default/support/sidebar.ts @@ -20,7 +20,7 @@ export function getSidebar( _sidebar: DefaultTheme.Sidebar | undefined, path: string ): SidebarItem[] { - if (Array.isArray(_sidebar)) return _sidebar + if (Array.isArray(_sidebar)) return addBase(_sidebar) if (_sidebar == null) return [] path = ensureStartingSlash(path) @@ -34,7 +34,10 @@ export function getSidebar( return path.startsWith(ensureStartingSlash(dir)) }) - return dir ? _sidebar[dir] : [] + const sidebar = dir ? _sidebar[dir] : [] + return Array.isArray(sidebar) + ? addBase(sidebar) + : addBase(sidebar.items, sidebar.base) } /** @@ -104,3 +107,13 @@ export function hasActiveLink( ? hasActiveLink(path, items.items) : false } + +function addBase(items: SidebarItem[], _base?: string): SidebarItem[] { + return [...items].map((_item) => { + const item = { ..._item } + const base = item.base || _base + if (base && item.link) item.link = base + item.link + if (item.items) item.items = addBase(item.items, base) + return item + }) +} diff --git a/types/default-theme.d.ts b/types/default-theme.d.ts index 1e88c91d..aa9ab6f3 100644 --- a/types/default-theme.d.ts +++ b/types/default-theme.d.ts @@ -202,7 +202,7 @@ export namespace DefaultTheme { export type Sidebar = SidebarItem[] | SidebarMulti export interface SidebarMulti { - [path: string]: SidebarItem[] + [path: string]: SidebarItem[] | { items: SidebarItem[]; base: string } } export type SidebarItem = { @@ -230,6 +230,11 @@ export namespace DefaultTheme { */ collapsed?: boolean + /** + * Base path for the children items. + */ + base?: string + /** * Customize text that appears on the footer of previous/next page. */