Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 23x 23x 23x 23x 23x 1x 22x | import { extractHeadings, extractLeadingHero, type RenderedMarkdown } from '@/lib/markdown';
import type { Crumb } from '@/components/Breadcrumbs';
import { DocShell } from '@/components/DocShell';
import { HeroSplit } from '@/components/HeroSplit';
import { PageFeedback } from '@/components/PageFeedback';
import { Pager, type PagerLink } from '@/components/Pager';
import { TabBar, type TabBarProps } from '@/components/TabBar';
import { ViewMarkdownButton } from '@/components/ViewMarkdownButton';
interface MarkdownPageProps extends RenderedMarkdown {
tabs?: TabBarProps['tabs'];
breadcrumbs?: Crumb[];
/**
* Raw markdown source for "Copy Markdown". Content pages pass it; the
* page-bottom actions, divider and pager render only then.
*/
markdown?: string;
/** Subtitle under the title. */
description?: string;
prev?: PagerLink | null;
next?: PagerLink | null;
/** A category's landing page: a leading hero renders as the full-bleed compact banner. */
isTopLevel?: boolean;
}
// Markdown source is trusted: authored in-repo, rendered at build time by the unified
// pipeline. No user-supplied HTML reaches this component.
export function MarkdownPage({
frontmatter,
html,
tabs,
breadcrumbs,
markdown,
description,
prev,
next,
isTopLevel = false,
}: MarkdownPageProps) {
// A leading hero carries the page title and background image; the layouts
// below rebuild it as a compact banner or a side image.
const { hero, rest, background } = extractLeadingHero(html);
const title = frontmatter.title;
const tabBar = tabs && tabs.length > 0 ? <TabBar tabs={tabs} /> : null;
const body = (
<>
<article className="content-blocks" dangerouslySetInnerHTML={{ __html: rest }} />
{markdown !== undefined && (
<>
{/* spacing-9 rhythm between content, actions, divider and pager. */}
<div className="page-actions">
<ViewMarkdownButton markdown={markdown} />
<PageFeedback />
</div>
<hr className="page-divider" />
<Pager prev={prev} next={next} />
</>
)}
</>
);
// Top-level landing: full-bleed compact banner with only the title. These are
// directory-style pages, so there's no in-page nav.
if (isTopLevel && hero) {
return (
<>
<div
className="hero-banner hero-banner--compact markdown-page__banner"
style={background ? { backgroundImage: background } : undefined}
>
{title && <h1>{title}</h1>}
</div>
<DocShell>
{description && <p className="text-subtitle markdown-page__subtitle">{description}</p>}
<div className="markdown-page__body">
{tabBar}
{body}
</div>
</DocShell>
</>
);
}
// Second level and below: breadcrumbs + title + subtitle, with the hero image
// (if any) as a half-width side image.
return (
<DocShell
toc={extractHeadings(rest)}
heading={
<>
<HeroSplit
breadcrumbs={breadcrumbs}
title={title}
description={description}
image={hero && background ? background : undefined}
/>
{tabBar}
</>
}
>
{body}
</DocShell>
);
}
|