import type { Metadata } from "next"; import Link from "next/link"; import type { ReactNode } from "react"; import { buildLegalSyntheticPost, type LegalDocumentMessages, type LegalDocumentSlug, } from "../../../lib/legalSyntheticPost"; import ContentBanner from "../../components/sections/ContentBanner"; type LegalDocumentPageProps = { slug: LegalDocumentSlug; path: string; page: LegalDocumentMessages; }; const INLINE_LINK = /\[([^\]]+)\]\(([^)]+)\)/g; const ARTICLE_COLUMN_CLASS = "mx-auto flex w-full flex-col gap-[var(--space-800,32px)] text-[var(--color-content-default-primary)] text-medium-paragraph sm:max-w-[390px] sm:text-large-paragraph md:max-w-[472px] lg:max-w-[700px] lg:text-x-large-paragraph xl:max-w-[904px] xl:text-xx-large-paragraph"; const LINK_CLASS = "underline decoration-solid underline-offset-2"; function isSafeHref(href: string): boolean { return ( (href.startsWith("/") && !href.startsWith("//")) || href.startsWith("https://") || href.startsWith("http://") || href.startsWith("mailto:") ); } function LegalInlineText({ text }: { text: string }) { const nodes: ReactNode[] = []; let lastIndex = 0; let key = 0; for (const match of text.matchAll(INLINE_LINK)) { const matchIndex = match.index ?? 0; if (matchIndex > lastIndex) { nodes.push(text.slice(lastIndex, matchIndex)); } const label = match[1]; const href = match[2]; if (isSafeHref(href)) { const isInternal = href.startsWith("/") && !href.startsWith("//"); nodes.push( isInternal ? ( {label} ) : ( {label} ), ); key += 1; } else { nodes.push(label); } lastIndex = matchIndex + match[0].length; } if (lastIndex < text.length) { nodes.push(text.slice(lastIndex)); } return nodes; } export function legalPageMetadata( meta: { title: string; description: string; keywords: string[] }, page: { banner: { title: string; description: string } }, ): Metadata { return { title: meta.title, description: meta.description, keywords: meta.keywords, openGraph: { title: page.banner.title, description: page.banner.description, type: "website", siteName: "CommunityRule", }, }; } /** * Public legal documents (`/privacy`, `/terms`, `/cookies`). * * Figma: "Content page Template" (19003:23305) — ContentBanner guide * (22078:806964) + article column (19003:23574). Body stacks follow * Type / Text Block (22001:29793): heading + paragraphs. Omits Related * articles, Ask Organizer, and decorative shapes. * https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=19003-23305 */ export default function LegalDocumentPage({ slug, path, page, }: LegalDocumentPageProps) { const post = buildLegalSyntheticPost(slug, page); const structuredData = { "@context": "https://schema.org", "@type": "WebPage", name: page.banner.title, description: page.banner.description, url: `https://communityrule.com${path}`, dateModified: page.banner.date, publisher: { "@type": "Organization", name: "CommunityRule", url: "https://communityrule.com", }, }; const breadcrumbData = { "@context": "https://schema.org", "@type": "BreadcrumbList", itemListElement: [ { "@type": "ListItem", position: 1, name: "Home", item: "https://communityrule.com", }, { "@type": "ListItem", position: 2, name: page.banner.title, item: `https://communityrule.com${path}`, }, ], }; return ( <>