Finalizes the docs section after an adversarial audit (code review + per-page fact-check + coherence critic) and two content requests. - Accuracy: fixed 10 invented cross-link slugs, the admin-vs-board gating claims the verifiers caught (permissions matrix, /settings, invites, onboarding, connect-payments, proposal withdraw, Stripe reconciliation, member fields, door.operate), and 2 issues in the new pages (project area-at-creation, forum thread-delete role). - Coverage: added 5 how-to pages so every module is documented (recurring Stripe dues, tasks & chores, projects, comms & forum, ops knowledge base + secrets vault). 34 pages total. - Screenshots: 12 captioned app screenshots under public/docs-media/, embedded as figures. Each tutorial now has 2-3 step screenshots. - Style: removed all em-dashes/en-dashes/ellipses from the docs (natural ASCII punctuation). - Handoff (docs/HANDOFF-audit-cleanup.md) updated with the current state. typecheck 0 · lint 0 errors · build ok (all 34 /docs pages prerendered)
50 lines
2.0 KiB
TypeScript
50 lines
2.0 KiB
TypeScript
import ReactMarkdown from 'react-markdown'
|
|
import remarkGfm from 'remark-gfm'
|
|
import { makeHeadingSlugger, isInDocumentHref } from '@/lib/markdown-anchors'
|
|
|
|
// Docs-brand markdown renderer. Unlike components/markdown.tsx (which is bound
|
|
// to the management app's theme tokens), this emits headings with stable anchor
|
|
// ids and otherwise leans on the `.docs-prose` stylesheet in docs.css so the
|
|
// output matches the public site's dark / monospace / lime aesthetic.
|
|
//
|
|
// Content here is author-trusted (checked-in .md), but we still never enable
|
|
// rehypeRaw, so any stray HTML stays inert.
|
|
export function DocsMarkdown({ content }: { content: string }) {
|
|
const slug = makeHeadingSlugger()
|
|
|
|
return (
|
|
<div className="docs-prose">
|
|
<ReactMarkdown
|
|
remarkPlugins={[remarkGfm]}
|
|
components={{
|
|
h1: ({ children }) => <h1 id={slug(children)}>{children}</h1>,
|
|
h2: ({ children }) => <h2 id={slug(children)}>{children}</h2>,
|
|
h3: ({ children }) => <h3 id={slug(children)}>{children}</h3>,
|
|
h4: ({ children }) => <h4 id={slug(children)}>{children}</h4>,
|
|
// Render images as captioned figures. Uses spans (valid inside the
|
|
// <p> react-markdown wraps a lone image in) styled as blocks; the alt
|
|
// text doubles as the caption.
|
|
img: ({ src, alt }) =>
|
|
typeof src === 'string' ? (
|
|
<span className="docs-figure">
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img src={src} alt={alt ?? ''} loading="lazy" />
|
|
{alt ? <span className="docs-figcaption">{alt}</span> : null}
|
|
</span>
|
|
) : null,
|
|
a: ({ href, children }) =>
|
|
isInDocumentHref(href) ? (
|
|
<a href={href}>{children}</a>
|
|
) : (
|
|
<a href={href} target="_blank" rel="noopener noreferrer">
|
|
{children}
|
|
</a>
|
|
),
|
|
}}
|
|
>
|
|
{content}
|
|
</ReactMarkdown>
|
|
</div>
|
|
)
|
|
}
|