export interface DashboardDocumentTitleParts { businessName: string dashboardName: string pageLabels?: string[] } /** Pattern: `{businessName} - {dashboardName} · {page}` */ export function formatDashboardDocumentTitle({ businessName, dashboardName, pageLabels = [], }: DashboardDocumentTitleParts): string { const business = businessName.trim() || 'Store' const dashboard = dashboardName.trim() const pages = pageLabels.map((label) => label.trim()).filter(Boolean) if (pages.length === 0) { return `${business} - ${dashboard}` } return `${business} - ${dashboard} · ${pages.join(' · ')}` } export interface RouteTitleRule { match: string | RegExp labels: string[] } export function normalizeRoutePath(pathname: string): string { const path = pathname.split('?')[0]?.split('#')[0] ?? '/' if (path === '/') return '/' return path.replace(/\/+$/, '') || '/' } export function resolveRoutePageLabels(pathname: string, rules: RouteTitleRule[]): string[] { const path = normalizeRoutePath(pathname) const sorted = [...rules].sort((a, b) => { const lenA = typeof a.match === 'string' ? a.match.length : 0 const lenB = typeof b.match === 'string' ? b.match.length : 0 return lenB - lenA }) for (const rule of sorted) { if (typeof rule.match === 'string' && rule.match === path) { return rule.labels } if (rule.match instanceof RegExp && rule.match.test(path)) { return rule.labels } } return [] }