From 6611088ccb766d102262a7a45c2df8714f2bfa7f Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 19 Mar 2025 00:24:25 -0500 Subject: [PATCH] feat: slugs --- .../src/pages/[...locale]/api/_index.tsx | 83 +++++++++++++++++++ .../src/pages/[...locale]/api/index.astro | 63 +++++++++++--- 2 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 packages/website/src/pages/[...locale]/api/_index.tsx diff --git a/packages/website/src/pages/[...locale]/api/_index.tsx b/packages/website/src/pages/[...locale]/api/_index.tsx new file mode 100644 index 000000000..9e13dc3ec --- /dev/null +++ b/packages/website/src/pages/[...locale]/api/_index.tsx @@ -0,0 +1,83 @@ +import { Code, Link, Table } from '@radix-ui/themes'; +import { useState } from 'react'; +import type { APIPath } from './index.astro'; + +interface SlugsTableProps { + slugs: APIPath['slugs']; +} + +const MAX_UNEXPANDED = 5; + +export function SlugsTable({ slugs }: SlugsTableProps) { + if (slugs === undefined) return null; + + const [expanded, setExpanded] = useState(false); + + return ( + + + + + + # + + + + {slugs.titles.map((title) => ( + + + {title} + + + ))} + + + + + {slugs.groups.map((group, groupIndex) => { + if (!expanded && groupIndex >= MAX_UNEXPANDED) return null; + + return ( + + + + {groupIndex} + + + + {slugs.titles.map((title) => ( + + + {group[title]} + + + ))} + + ); + })} + + + + { + event.preventDefault(); + setExpanded((state) => !state); + }} + > + {expanded + ? 'Show less' + : `View all ${slugs.groups.length.toLocaleString('en')} slugs`} + + + + + ); +} diff --git a/packages/website/src/pages/[...locale]/api/index.astro b/packages/website/src/pages/[...locale]/api/index.astro index 74909f454..b60c2e1d9 100644 --- a/packages/website/src/pages/[...locale]/api/index.astro +++ b/packages/website/src/pages/[...locale]/api/index.astro @@ -1,8 +1,10 @@ --- import { Code, Flex, Heading, Separator } from '@radix-ui/themes'; +import type { GetStaticPaths, GetStaticPathsOptions } from 'astro'; import { PageWrapper } from '../../../components/PageWrapper'; import { apiTool } from '../../../constants/tools'; import ToolLayout from '../../../layouts/ToolLayout.astro'; +import { SlugsTable } from './_index'; export { getStaticPaths } from '../index.astro'; @@ -12,27 +14,63 @@ interface Tag { description?: string; } +export interface APIPath { + path: string; + content: string; + comment: string; + tags: Tag[]; + slugs?: { + titles: string[]; + groups: SlugGroup[]; + }; +} + +type SlugGroup = Record; + const getDocsRegex = /\/\*\*\n(( \*(.+)?\n?)+)\n \*\/\nexport const GET/; const multiLineCommentPrefixRegex = /^ \* ?/gm; const tagRegex = /(@[^\s]+)(?:\s(.+))?/; const firstWordRegex = /(\S+)(?:\s(.+))?/; const ROOT = '/src/pages/api/'; -const glob = import.meta.glob('/src/pages/api/**/*.ts', { +const globRaw = import.meta.glob('/src/pages/api/**/*.ts', { eager: true, query: '?raw', import: 'default', -}); -let apis: { - path: string; - content: string; - comment: string; - tags: Tag[]; -}[] = []; +}) as Record; +const globStaticPaths = import.meta.glob('/src/pages/api/**/*.ts', { + eager: true, + import: 'getStaticPaths', +}) as Record; +let apis: APIPath[] = []; -for (const rawPath in glob) { - const content = (glob[rawPath] as string).replaceAll('\r', ''); +for (const rawPath in globRaw) { + const content = globRaw[rawPath].replaceAll('\r', ''); const regexExecution = content.match(getDocsRegex); const commentRaw = regexExecution?.[1]; + const getStaticPaths = globStaticPaths[rawPath]; + let slugs: APIPath['slugs'] | undefined; + + if (getStaticPaths) { + const staticPaths = await getStaticPaths( + undefined as unknown as GetStaticPathsOptions, + ); + + const titles = new Set(); + + slugs = { + titles: [], + groups: [], + }; + + staticPaths.forEach((path) => { + Object.keys(path.params).forEach((key) => { + titles.add(key); + }); + slugs!.groups.push(path.params); + }); + + slugs.titles = [...titles]; + } if (!commentRaw) continue; @@ -72,8 +110,7 @@ for (const rawPath in glob) { }); comment = comment.trim(); - - apis.push({ path, content, comment, tags }); + apis.push({ path, content, comment, tags, slugs }); } apis.sort((a, b) => a.path.localeCompare(b.path)); @@ -126,6 +163,8 @@ apis.sort((a, b) => a.path.localeCompare(b.path)); )} + + {index < apis.length - 1 && ( )}