import type { Settings } from "@/db/schema"; export const FEED_PATH = "/feed.xml"; /** * Canonical + RSS-autodiscovery alternates for a public page. Next.js * merges metadata SHALLOWLY per key, so a page that sets only * `alternates.canonical` would wipe the RSS link inherited from the * root layout — always set both through this helper. */ export function pageAlternates(canonical: string) { return { canonical, types: { "application/rss+xml": FEED_PATH }, }; } /** * The site's public origin for canonical URLs, feeds, and the sitemap. * Preference order: the admin-configured setting, the SITE_URL env var, * then localhost so development still produces valid (if wrong) URLs. * Always returned without a trailing slash. */ export function resolveSiteUrl(settings: Pick): string { const configured = settings.siteUrl || process.env.SITE_URL || "http://localhost:3000"; return configured.replace(/\/+$/, ""); } export function absoluteUrl(siteUrl: string, path: string): string { return `${siteUrl}${path.startsWith("/") ? path : `/${path}`}`; } /** * Rewrites site-relative src/href attributes ("/uploads/…", "/posts/…") * to absolute URLs. Feed readers resolve nothing relative to the feed, * so stored HTML must be absolutified before it goes into RSS. */ export function absolutifyHtml(html: string, siteUrl: string): string { return html.replace( /(src|href)="(\/(?!\/)[^"]*)"/g, (_m, attr: string, path: string) => `${attr}="${siteUrl}${path}"`, ); }