feat(api-extractor): support multiple entrypoints (#10829)

* feat(api-extractor): support multiple entrypoints

* chore: initial support in generateSplitDocumentation

* chore: bring in line with upstream

* refactor: multiple entrypoints in scripts

* fix: split docs

* feat: website

* fix: docs failing on next

* fix: don't include dtypes for now

* refactor: don't fetch entrypoint if there is none

---------

Co-authored-by: iCrawl <buechler.noel@outlook.com>
This commit is contained in:
Qjuh
2025-05-12 23:48:41 +02:00
committed by GitHub
parent 4f5e5c7c14
commit b3db92edfb
93 changed files with 2330 additions and 1956 deletions

View File

@@ -4,6 +4,7 @@ import { VscGithubInverted } from '@react-icons/all-files/vsc/VscGithubInverted'
import type { Metadata } from 'next';
import Link from 'next/link';
import { Suspense, type PropsWithChildren } from 'react';
import { EntryPointSelect } from '@/components/EntrypointSelect';
import { Footer } from '@/components/Footer';
import { Navigation } from '@/components/Navigation';
import { Scrollbars } from '@/components/OverlayScrollbars';
@@ -13,14 +14,21 @@ import { ThemeSwitchNoSRR } from '@/components/ThemeSwitch';
import { VersionSelect } from '@/components/VersionSelect';
import { Sidebar, SidebarContent, SidebarHeader, SidebarInset, SidebarTrigger } from '@/components/ui/Sidebar';
import { buttonStyles } from '@/styles/ui/button';
import { PACKAGES_WITH_ENTRY_POINTS } from '@/util/constants';
import { ENV } from '@/util/env';
import { fetchEntryPoints } from '@/util/fetchEntryPoints';
import { fetchVersions } from '@/util/fetchVersions';
import { parseDocsPathParams } from '@/util/parseDocsPathParams';
import { CmdK } from './CmdK';
export async function generateMetadata({
params,
}: {
readonly params: Promise<{ readonly packageName: string; readonly version: string }>;
readonly params: Promise<{
readonly item?: string[] | undefined;
readonly packageName: string;
readonly version: string;
}>;
}): Promise<Metadata> {
const { packageName, version } = await params;
@@ -35,11 +43,22 @@ export async function generateMetadata({
export default async function Layout({
params,
children,
}: PropsWithChildren<{ readonly params: Promise<{ readonly packageName: string; readonly version: string }> }>) {
const { packageName, version } = await params;
}: PropsWithChildren<{
readonly params: Promise<{
readonly item?: string[] | undefined;
readonly packageName: string;
readonly version: string;
}>;
}>) {
const { packageName, version, item } = await params;
const versions = fetchVersions(packageName);
const hasEntryPoints = PACKAGES_WITH_ENTRY_POINTS.includes(packageName);
const entryPoints = hasEntryPoints ? fetchEntryPoints(packageName, version) : Promise.resolve([]);
const { entryPoints: parsedEntrypoints } = parseDocsPathParams(item);
return (
<>
<Sidebar closeButton={false} intent="inset">
@@ -65,12 +84,13 @@ export default async function Layout({
<PackageSelect />
{/* <h3 className="p-1 text-lg font-semibold">{version}</h3> */}
<VersionSelect versionsPromise={versions} />
{hasEntryPoints ? <EntryPointSelect entryPointsPromise={entryPoints} /> : null}
<SearchButton />
</div>
</SidebarHeader>
<SidebarContent className="bg-[#f3f3f4] p-0 py-4 pl-4 dark:bg-[#121214]">
<Scrollbars>
<Navigation packageName={packageName} version={version} />
<Navigation entryPoint={parsedEntrypoints.join('.')} packageName={packageName} version={version} />
</Scrollbars>
</SidebarContent>
</Sidebar>

View File

@@ -0,0 +1,99 @@
'use cache';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import rehypeShikiFromHighlighter from '@shikijs/rehype/core';
import type { Metadata } from 'next';
import { MDXRemote } from 'next-mdx-remote-client/rsc';
import remarkGfm from 'remark-gfm';
import { DocItem } from '@/components/DocItem';
import { fetchNode } from '@/util/fetchNode';
import { parseDocsPathParams } from '@/util/parseDocsPathParams';
import { getSingletonHighlighter } from '@/util/shiki.bundle';
export async function generateMetadata({
params,
}: {
readonly params: Promise<{
readonly item?: string[] | undefined;
readonly packageName: string;
readonly version: string;
}>;
}): Promise<Metadata> {
const { item, packageName, version } = await params;
const { foundItem } = parseDocsPathParams(item);
if (!foundItem) {
return {
title: `${packageName} (${version})`,
};
}
const decodedItemName = decodeURIComponent(foundItem);
const titlePart = decodedItemName.split(':')?.[0] ?? decodedItemName;
return {
title: `${titlePart} (${packageName} - ${version})`,
};
}
export default async function Page({
params,
}: {
readonly params: Promise<{
readonly item?: string[] | undefined;
readonly packageName: string;
readonly version: string;
}>;
}) {
const { item, packageName, version } = await params;
const { entryPoints: parsedEntrypoints, foundItem } = parseDocsPathParams(item);
if (!foundItem) {
const fileContent = await readFile(join(process.cwd(), `src/assets/readme/${packageName}/home-README.md`), 'utf8');
return (
<div className="prose prose-neutral dark:prose-invert prose-a:[&>img]:inline-block prose-a:[&>img]:m-0 prose-a:[&>img[height='44']]:h-11 prose-p:my-2 prose-pre:py-3 prose-pre:rounded-sm prose-pre:px-0 prose-pre:border prose-pre:border-[#d4d4d4] dark:prose-pre:border-[#404040] prose-code:font-normal prose-a:text-[#5865F2] prose-a:no-underline prose-a:hover:text-[#3d48c3] dark:prose-a:hover:text-[#7782fa] mx-auto max-w-screen-xl px-6 py-6 [&_code_span:last-of-type:empty]:hidden [&_div[align='center']_p_a+a]:ml-2">
<MDXRemote
options={{
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
[
rehypeShikiFromHighlighter,
await getSingletonHighlighter({
langs: ['typescript', 'javascript', 'shellscript'],
themes: ['github-light', 'github-dark-dimmed'],
}),
{
themes: {
light: 'github-light',
dark: 'github-dark-dimmed',
},
},
],
],
},
}}
source={fileContent}
/>
</div>
);
}
const entryPointString = parsedEntrypoints.join('.');
const node = await fetchNode({
entryPoint: entryPointString,
item: decodeURIComponent(foundItem),
packageName,
version,
});
return (
<main className="mx-auto flex w-full max-w-screen-xl flex-col gap-8 px-6 py-4">
<DocItem node={node} packageName={packageName} version={version} />
</main>
);
}

View File

@@ -1,44 +0,0 @@
'use cache';
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { DocItem } from '@/components/DocItem';
import { fetchNode } from '@/util/fetchNode';
export async function generateMetadata({
params,
}: {
readonly params: Promise<{
readonly item: string;
readonly packageName: string;
readonly version: string;
}>;
}): Promise<Metadata> {
const { item, packageName, version } = await params;
const normalizeItem = item.split(encodeURIComponent(':'))[0];
return {
title: `${normalizeItem} (${packageName} - ${version})`,
};
}
export default async function Page({
params,
}: {
readonly params: Promise<{ readonly item: string; readonly packageName: string; readonly version: string }>;
}) {
const { item, packageName, version } = await params;
const node = await fetchNode({ item, packageName, version });
if (!node) {
notFound();
}
return (
<main className="mx-auto flex w-full max-w-screen-xl flex-col gap-8 px-6 py-4">
<DocItem node={node} packageName={packageName} version={version} />
</main>
);
}

View File

@@ -1,42 +0,0 @@
'use cache';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import rehypeShikiFromHighlighter from '@shikijs/rehype/core';
import { MDXRemote } from 'next-mdx-remote-client/rsc';
import remarkGfm from 'remark-gfm';
import { getSingletonHighlighter } from '@/util/shiki.bundle';
export default async function Page({ params }: { readonly params: Promise<{ readonly packageName: string }> }) {
const { packageName } = await params;
const fileContent = await readFile(join(process.cwd(), `src/assets/readme/${packageName}/home-README.md`), 'utf8');
return (
<div className="prose prose-neutral dark:prose-invert prose-a:[&>img]:inline-block prose-a:[&>img]:m-0 prose-a:[&>img[height='44']]:h-11 prose-p:my-2 prose-pre:py-3 prose-pre:rounded-sm prose-pre:px-0 prose-pre:border prose-pre:border-[#d4d4d4] dark:prose-pre:border-[#404040] prose-code:font-normal prose-a:text-[#5865F2] prose-a:no-underline prose-a:hover:text-[#3d48c3] dark:prose-a:hover:text-[#7782fa] mx-auto max-w-screen-xl px-6 py-6 [&_code_span:last-of-type:empty]:hidden [&_div[align='center']_p_a+a]:ml-2">
<MDXRemote
options={{
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
[
rehypeShikiFromHighlighter,
await getSingletonHighlighter({
langs: ['typescript', 'javascript', 'shellscript'],
themes: ['github-light', 'github-dark-dimmed'],
}),
{
themes: {
light: 'github-light',
dark: 'github-dark-dimmed',
},
},
],
],
},
}}
source={fileContent}
/>
</div>
);
}