Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/website/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./../../dist/apps/website/.next/types/routes.d.ts";
import "./.next/dev/types/routes.d.ts";

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
19 changes: 15 additions & 4 deletions apps/website/src/app/docs/[library]/[section]/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { getDocBySlug, getAllDocSlugs, getDocMetadata } from '../../../../../lib
import { ApiDocRenderer, type ApiDocEntry } from '../../../../../components/docs/ApiDocRenderer';
import { DocsTOC } from '../../../../../components/docs/DocsTOC';
import { extractHeadings } from '../../../../../lib/extract-headings';
import { getLibraryConfig, type LibraryId } from '../../../../../lib/docs-config';
import { findDocsPage, getLibraryConfig, type LibraryId } from '../../../../../lib/docs-config';
import fs from 'fs';
import path from 'path';

Expand Down Expand Up @@ -84,10 +84,21 @@ export default async function DocsPage({ params }: DocsRouteProps) {
{section === 'api' && (() => {
const entries = loadApiDocs(library);
const target = doc.title.replace(/\(\)$/, '');
const apiEntry = entries.find((e: ApiDocEntry) => e.name === target || e.name === doc.title);
return apiEntry ? (
const byName = (name: string) =>
entries.find((e: ApiDocEntry) => e.name === name);

// A page normally documents the one export named by its H1. Pages
// covering a group of exports declare them via `apiEntries`.
const configured = findDocsPage(library, section, slug)?.apiEntries;
const rendered = configured
? configured.map(byName).filter((e): e is ApiDocEntry => Boolean(e))
: [byName(target) ?? byName(doc.title)].filter((e): e is ApiDocEntry => Boolean(e));

return rendered.length > 0 ? (
<div className="px-6 md:px-12 max-w-3xl pb-8">
<ApiDocRenderer entry={apiEntry} />
{rendered.map((entry) => (
<ApiDocRenderer key={entry.name} entry={entry} />
))}
</div>
) : null;
})()}
Expand Down
23 changes: 22 additions & 1 deletion apps/website/src/lib/docs-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ export interface DocsPage {
title: string;
slug: string;
section: string;
/**
* API pages auto-render the generated `api-docs.json` entry whose name
* matches the page's H1. Set this on a page that covers a *group* of exports
* instead — each named entry is rendered in order, below the page prose.
*/
apiEntries?: string[];
}

export interface DocsSection {
Expand Down Expand Up @@ -367,7 +373,22 @@ export const docsConfig: DocsLibrary[] = [
id: 'api',
color: 'blue',
pages: [
{ title: 'LangGraph.js Helpers', slug: 'client-tool-helpers', section: 'api' },
{
title: 'LangGraph.js Helpers',
slug: 'client-tool-helpers',
section: 'api',
apiEntries: [
'bindClientTools',
'clientToolsChannel',
'clientToolsRouter',
'clientToolSpecs',
'clientToolNames',
'hasClientToolCall',
'hasServerToolCall',
'routeAfterAgent',
'lastMessage',
],
},
],
},
],
Expand Down
17 changes: 14 additions & 3 deletions apps/website/src/lib/docs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { getAllDocSlugs, getDocBySlug, getDocMetadata } from './docs';
import { allDocsPages, specialDocsPages } from './docs-config';
import { allDocsPages, findDocsPage, specialDocsPages } from './docs-config';
import { getCanonicalUrl, getSitemapRoutes } from './site-metadata';

const internalDocsLinkPattern = /(?:href=["']|\]\()(?<href>\/docs\/[^"')#\s]+)/g;
Expand Down Expand Up @@ -226,9 +226,20 @@ describe('website docs bindings', () => {

const apiDocsPath = path.join(contentRoot, library, 'api', 'api-docs.json');
const entries = JSON.parse(fs.readFileSync(apiDocsPath, 'utf8')) as Array<{ name: string }>;
const names = new Set(entries.map((entry) => entry.name));

// Group pages declare the exports they cover; every one must exist.
const configured = findDocsPage(library, section, slug)?.apiEntries;
if (configured) {
const missing = configured.filter((name) => !names.has(name));
if (missing.length > 0) {
unresolvedApiPages.push(`${library}/api/${slug} → ${missing.join(', ')}`);
}
continue;
}

const pageTitle = doc.title.replace(/\(\)$/, '');
const candidates = [pageTitle, doc.title];
if (!entries.some((entry) => candidates.includes(entry.name))) {
if (!names.has(pageTitle) && !names.has(doc.title)) {
unresolvedApiPages.push(`${library}/api/${slug}`);
}
}
Expand Down
2 changes: 1 addition & 1 deletion apps/website/tsconfig.tsbuildinfo

Large diffs are not rendered by default.

Loading