mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: slugs
This commit is contained in:
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 { Code, Flex, Heading, Separator } from '@radix-ui/themes';
|
||||||
|
import type { GetStaticPaths, GetStaticPathsOptions } from 'astro';
|
||||||
import { PageWrapper } from '../../../components/PageWrapper';
|
import { PageWrapper } from '../../../components/PageWrapper';
|
||||||
import { apiTool } from '../../../constants/tools';
|
import { apiTool } from '../../../constants/tools';
|
||||||
import ToolLayout from '../../../layouts/ToolLayout.astro';
|
import ToolLayout from '../../../layouts/ToolLayout.astro';
|
||||||
|
import { SlugsTable } from './_index';
|
||||||
|
|
||||||
export { getStaticPaths } from '../index.astro';
|
export { getStaticPaths } from '../index.astro';
|
||||||
|
|
||||||
@@ -12,27 +14,63 @@ interface Tag {
|
|||||||
description?: string;
|
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 getDocsRegex = /\/\*\*\n(( \*(.+)?\n?)+)\n \*\/\nexport const GET/;
|
||||||
const multiLineCommentPrefixRegex = /^ \* ?/gm;
|
const multiLineCommentPrefixRegex = /^ \* ?/gm;
|
||||||
const tagRegex = /(@[^\s]+)(?:\s(.+))?/;
|
const tagRegex = /(@[^\s]+)(?:\s(.+))?/;
|
||||||
const firstWordRegex = /(\S+)(?:\s(.+))?/;
|
const firstWordRegex = /(\S+)(?:\s(.+))?/;
|
||||||
const ROOT = '/src/pages/api/';
|
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,
|
eager: true,
|
||||||
query: '?raw',
|
query: '?raw',
|
||||||
import: 'default',
|
import: 'default',
|
||||||
});
|
}) as Record<string, string>;
|
||||||
let apis: {
|
const globStaticPaths = import.meta.glob('/src/pages/api/**/*.ts', {
|
||||||
path: string;
|
eager: true,
|
||||||
content: string;
|
import: 'getStaticPaths',
|
||||||
comment: string;
|
}) as Record<string, GetStaticPaths | undefined>;
|
||||||
tags: Tag[];
|
let apis: APIPath[] = [];
|
||||||
}[] = [];
|
|
||||||
|
|
||||||
for (const rawPath in glob) {
|
for (const rawPath in globRaw) {
|
||||||
const content = (glob[rawPath] as string).replaceAll('\r', '');
|
const content = globRaw[rawPath].replaceAll('\r', '');
|
||||||
const regexExecution = content.match(getDocsRegex);
|
const regexExecution = content.match(getDocsRegex);
|
||||||
const commentRaw = regexExecution?.[1];
|
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;
|
if (!commentRaw) continue;
|
||||||
|
|
||||||
@@ -72,8 +110,7 @@ for (const rawPath in glob) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
comment = comment.trim();
|
comment = comment.trim();
|
||||||
|
apis.push({ path, content, comment, tags, slugs });
|
||||||
apis.push({ path, content, comment, tags });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apis.sort((a, b) => a.path.localeCompare(b.path));
|
apis.sort((a, b) => a.path.localeCompare(b.path));
|
||||||
@@ -126,6 +163,8 @@ apis.sort((a, b) => a.path.localeCompare(b.path));
|
|||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
|
<SlugsTable client:load slugs={api.slugs} />
|
||||||
|
|
||||||
{index < apis.length - 1 && (
|
{index < apis.length - 1 && (
|
||||||
<Separator size="4" style={{ height: 0.5 }} />
|
<Separator size="4" style={{ height: 0.5 }} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in new issue
Block a user