import siteData from '@siteData' import { useDark } from '@vueuse/core' import { computed, inject, readonly, ref, shallowRef, type InjectionKey, type Ref } from 'vue' import { APPEARANCE_KEY, createTitle, resolveSiteDataByRoute, type PageData, type SiteData } from '../shared' import type { Route } from './router' export const dataSymbol: InjectionKey = Symbol() export interface VitePressData { /** * Site-level metadata */ site: Ref> /** * themeConfig from .vitepress/config.js */ theme: Ref /** * Page-level metadata */ page: Ref /** * page frontmatter data */ frontmatter: Ref /** * dynamic route params */ params: Ref title: Ref description: Ref lang: Ref isDark: Ref dir: Ref localeIndex: Ref } // site data is a singleton export const siteDataRef: Ref = shallowRef( (import.meta.env.PROD ? siteData : readonly(siteData)) as SiteData ) // hmr if (import.meta.hot) { import.meta.hot.accept('/@siteData', (m) => { if (m) { siteDataRef.value = m.default } }) } // per-app data export function initData(route: Route): VitePressData { const site = computed(() => resolveSiteDataByRoute(siteDataRef.value, route.data.relativePath) ) const isDark = site.value.appearance ? useDark({ storageKey: APPEARANCE_KEY, initialValue: () => typeof site.value.appearance === 'string' ? site.value.appearance : 'auto', ...(typeof site.value.appearance === 'object' ? site.value.appearance : {}) }) : ref(false) return { site, theme: computed(() => site.value.themeConfig), page: computed(() => route.data), frontmatter: computed(() => route.data.frontmatter), params: computed(() => route.data.params), lang: computed(() => site.value.lang), dir: computed(() => site.value.dir), localeIndex: computed(() => site.value.localeIndex || 'root'), title: computed(() => { return createTitle(site.value, route.data) }), description: computed(() => { return route.data.description || site.value.description }), isDark } } export function useData(): VitePressData { const data = inject(dataSymbol) if (!data) { throw new Error('vitepress data not properly injected in app') } return data }