import { watch, getCurrentInstance, onBeforeUnmount, type App, type WatchStopHandle, } from 'vue' interface PageMeta { title?: string emoji?: string icon?: string } type PageMetaFunction = () => PageMeta | null | undefined type StopWatcherFunction = () => void let faviconRef: HTMLLinkElement | null = null let defaultFavIcon: string | null = null function initializeFavicon(): void { if (typeof window !== 'undefined' && !faviconRef) { faviconRef = document.querySelector('link[rel="icon"]') defaultFavIcon = faviconRef?.href || null } } export function usePageMeta(fn: PageMetaFunction): StopWatcherFunction { // Initialize favicon if we're on the client if (typeof window !== 'undefined') { initializeFavicon() } const stopWatcher: WatchStopHandle = watch( () => { try { return fn() } catch (error) { if (process.env.NODE_ENV === 'development') { console.warn('Failed to parse pageMeta in', fn) console.error(error) } return null } }, (pageMeta: PageMeta | null | undefined) => { // Only execute on client side if (typeof window === 'undefined') return if (!pageMeta) return if (pageMeta.title) { document.title = pageMeta.title } // Ensure favicon ref is initialized if (!faviconRef) initializeFavicon() if (pageMeta.emoji) { const href = `data:image/svg+xml,${pageMeta.emoji}` if (faviconRef) faviconRef.href = href } else if (pageMeta.icon) { if (faviconRef) faviconRef.href = pageMeta.icon } else { if (faviconRef && defaultFavIcon) faviconRef.href = defaultFavIcon } }, { immediate: true, deep: true, }, ) // Auto-cleanup if called within a component (like