import { inBrowser, onContentUpdated, useRoute } from 'vitepress'; import { computed, shallowReadonly, shallowRef, watch } from 'vue'; import { getSidebar, getSidebarGroups } from '../support/sidebar'; import { useData } from './data'; import { getHeaders } from './outline'; import { useCloseSidebarOnEscape } from './sidebar'; const headers = shallowRef([]); const sidebar = shallowRef([]); const is960 = shallowRef(false); export function useLayout() { const { frontmatter, theme } = useData(); const isHome = computed(() => { return !!(frontmatter.value.isHome ?? frontmatter.value.layout === 'home'); }); const hasSidebar = computed(() => { return (frontmatter.value.sidebar !== false && sidebar.value.length > 0 && !isHome.value); }); const isSidebarEnabled = computed(() => hasSidebar.value && is960.value); const sidebarGroups = computed(() => { return hasSidebar.value ? getSidebarGroups(sidebar.value) : []; }); const hasAside = computed(() => { if (isHome.value) return false; if (frontmatter.value.aside != null) return !!frontmatter.value.aside; return theme.value.aside !== false; }); const leftAside = computed(() => { if (!hasAside.value) return false; return frontmatter.value.aside == null ? theme.value.aside === 'left' : frontmatter.value.aside === 'left'; }); const hasLocalNav = computed(() => { return headers.value.length > 0; }); return { isHome, sidebar: shallowReadonly(sidebar), sidebarGroups, hasSidebar, isSidebarEnabled, hasAside, leftAside, headers: shallowReadonly(headers), hasLocalNav }; } export function registerWatchers({ closeSidebar }) { const { frontmatter, page, theme } = useData(); watch(() => [page.value.relativePath, theme.value.sidebar], ([relativePath, sidebarConfig]) => { const newSidebar = sidebarConfig ? getSidebar(sidebarConfig, relativePath) : []; if (JSON.stringify(newSidebar) !== JSON.stringify(sidebar.value)) { sidebar.value = newSidebar; } }, { immediate: true, deep: true, flush: 'sync' }); onContentUpdated(() => { headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline); }); if (inBrowser) { is960.value = window.innerWidth >= 960; window.addEventListener('resize', () => { is960.value = window.innerWidth >= 960; }, { passive: true }); } const route = useRoute(); watch(() => route.path, closeSidebar); useCloseSidebarOnEscape(closeSidebar); } export const layoutInfoInjectionKey = Symbol('layout-info');