feat: slugs

This commit is contained in:
tresabhi committed 2025-03-19 00:24:25 -05:00
1 parent 8d4933dd60
commit 6611088ccb
2 files changed
+134 -12

No files matched your search

@@ -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 (
<Table.Root variant="surface">
<Table.Header>
<Table.Row>
<Table.ColumnHeaderCell width="0">
<Code variant="ghost" color="gray">
#
</Code>
</Table.ColumnHeaderCell>
{slugs.titles.map((title) => (
<Table.ColumnHeaderCell>
<Code variant="ghost" color="gray" highContrast>
{title}
</Code>
</Table.ColumnHeaderCell>
))}
</Table.Row>
</Table.Header>
<Table.Body>
{slugs.groups.map((group, groupIndex) => {
if (!expanded && groupIndex >= MAX_UNEXPANDED) return null;
return (
<Table.Row>
<Table.RowHeaderCell>
<Code variant="ghost" color="gray">
{groupIndex}
</Code>
</Table.RowHeaderCell>
{slugs.titles.map((title) => (
<Table.Cell>
<Code variant="ghost" color="gray" highContrast>
{group[title]}
</Code>
</Table.Cell>
))}
</Table.Row>
);
})}
<Table.Row style={{ position: 'relative' }}>
<Table.Cell />
<Link
href="#"
underline="always"
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
}}
onClick={(event) => {
event.preventDefault();
setExpanded((state) => !state);
}}
>
{expanded
? 'Show less'
: `View all ${slugs.groups.length.toLocaleString('en')} slugs`}
</Link>
</Table.Row>
</Table.Body>
</Table.Root>
);
}
@@ -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<string, string | number | undefined>;
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<string, string>;
const globStaticPaths = import.meta.glob('/src/pages/api/**/*.ts', {
eager: true,
import: 'getStaticPaths',
}) as Record<string, GetStaticPaths | undefined>;
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<string>();
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));
)}
</Flex>
<SlugsTable client:load slugs={api.slugs} />
{index < apis.length - 1 && (
<Separator size="4" style={{ height: 0.5 }} />
)}