diff --git a/apps/website/src/components/CmdK.tsx b/apps/website/src/components/CmdK.tsx index 6941e29d2..ed75819d0 100644 --- a/apps/website/src/components/CmdK.tsx +++ b/apps/website/src/components/CmdK.tsx @@ -17,7 +17,7 @@ import { useKey } from 'react-use'; import { useCmdK } from '~/contexts/cmdK'; import { client } from '~/util/search'; -function resolveIcon(item: keyof ApiItemKind) { +function resolveIcon(item: keyof typeof ApiItemKind) { switch (item) { case 'Class': return ; @@ -29,7 +29,7 @@ function resolveIcon(item: keyof ApiItemKind) { return ; case 'TypeAlias': return ; - case 'Variables': + case 'Variable': return ; default: return ; diff --git a/apps/website/src/pages/_document.tsx b/apps/website/src/pages/_document.tsx index 9b6d87acc..f03dc1129 100644 --- a/apps/website/src/pages/_document.tsx +++ b/apps/website/src/pages/_document.tsx @@ -19,7 +19,7 @@ export default function Document() { - + diff --git a/apps/website/src/pages/api/og.tsx b/apps/website/src/pages/api/og.tsx index f210ad02e..178b45e4b 100644 --- a/apps/website/src/pages/api/og.tsx +++ b/apps/website/src/pages/api/og.tsx @@ -1,14 +1,9 @@ /* eslint-disable react/no-unknown-property */ import { ImageResponse } from '@vercel/og'; -const fonts = Promise.all([ - // fetch(new URL('../../assets/fonts/Inter-Light.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()), - // fetch(new URL('../../assets/fonts/Inter-Regular.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()), - // fetch(new URL('../../assets/fonts/Inter-Medium.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()), - // fetch(new URL('../../assets/fonts/Inter-SemiBold.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()), - // fetch(new URL('../../assets/fonts/Inter-Bold.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()), - fetch(new URL('../../assets/fonts/Inter-Black.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()), -]); +const fonts = fetch(new URL('../../assets/fonts/Inter-Black.ttf', import.meta.url)).then(async (res) => + res.arrayBuffer(), +); export default async function handler() { const fontData = await fonts; @@ -19,14 +14,14 @@ export default async function handler() { style={{ fontFamily: 'Inter', }} - tw="flex bg-[#181818] h-full w-full" + tw="flex flex-row bg-[#181818] h-full w-full" > -
-
-
-
-
- The most popular +
+
+
+
+
+ The most popular
way to build Discord bots. @@ -39,14 +34,7 @@ export default async function handler() { { width: 1_200, height: 630, - fonts: [ - // { name: 'Inter', data: fontData[0], weight: 300, style: 'normal' }, - // { name: 'Inter', data: fontData[1], weight: 400, style: 'normal' }, - // { name: 'Inter', data: fontData[2], weight: 500, style: 'normal' }, - // { name: 'Inter', data: fontData[3], weight: 600, style: 'normal' }, - // { name: 'Inter', data: fontData[4], weight: 700, style: 'normal' }, - { name: 'Inter', data: fontData[0], weight: 900, style: 'normal' }, - ], + fonts: [{ name: 'Inter', data: fontData, weight: 900, style: 'normal' }], }, ); } diff --git a/apps/website/src/pages/api/og_model.tsx b/apps/website/src/pages/api/og_model.tsx new file mode 100644 index 000000000..66ec4f1b2 --- /dev/null +++ b/apps/website/src/pages/api/og_model.tsx @@ -0,0 +1,170 @@ +/* eslint-disable react/no-unknown-property */ +import type { ApiItemKind } from '@microsoft/api-extractor-model'; +import { ImageResponse } from '@vercel/og'; +import type { NextRequest } from 'next/server'; + +const fonts = Promise.all([ + fetch(new URL('../../assets/fonts/Inter-Regular.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()), + fetch(new URL('../../assets/fonts/Inter-Bold.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()), +]); + +function resolveIcon(icon: keyof typeof ApiItemKind, size = 88) { + switch (icon) { + case 'Class': + return ( + + + + ); + case 'Enum': + return ( + + + + ); + case 'EnumMember': + return ( + + + + ); + case 'Interface': + return ( + + + + ); + case 'TypeAlias': + return ( + + + + ); + case 'Variable': + return ( + + + + ); + case 'Property': + return ( + + + + ); + default: + return ( + + + + ); + } +} + +export default async function handler(req: NextRequest) { + const fontData = await fonts; + + const { searchParams } = new URL(req.url); + + const hasPkg = searchParams.has('pkg'); + const hasKind = searchParams.has('kind'); + const hasName = searchParams.has('name'); + const hasMethods = searchParams.has('methods'); + const hasProps = searchParams.has('props'); + const hasMembers = searchParams.has('members'); + const pkg = hasPkg ? searchParams.get('pkg') : ''; + const kind = hasKind ? searchParams.get('kind')! : 'Method'; + const name = hasName ? searchParams.get('name')!.slice(0, 100) : 'My default name which is super long to overflow'; + const methods = hasMethods ? searchParams.get('methods') : ''; + const props = hasProps ? searchParams.get('props') : ''; + const members = hasMembers ? searchParams.get('members') : ''; + + return new ImageResponse( + ( +
+
+
@discordjs/{pkg}
+
+
+ {resolveIcon(kind as keyof typeof ApiItemKind)} +

+ {name} +

+
+
+
+ {props ? ( +
+ {resolveIcon('Property', 36)} +
+ {props} + Properties +
+
+ ) : null} + {methods ? ( +
+ {resolveIcon('Method', 36)} +
+ {methods} + Methods +
+
+ ) : null} + {members ? ( +
+ {resolveIcon('EnumMember', 36)} +
+ {members} + Members +
+
+ ) : null} +
+
+ discord.js +
+
+
+
+
+ ), + { + width: 1_200, + height: 630, + fonts: [ + { name: 'Inter', data: fontData[0], weight: 500, style: 'normal' }, + { name: 'Inter', data: fontData[1], weight: 700, style: 'normal' }, + ], + debug: false, + }, + ); +} + +export const config = { + runtime: 'experimental-edge', +}; diff --git a/apps/website/src/pages/docs/[...slug].tsx b/apps/website/src/pages/docs/[...slug].tsx index 62edade89..3d11f7705 100644 --- a/apps/website/src/pages/docs/[...slug].tsx +++ b/apps/website/src/pages/docs/[...slug].tsx @@ -1,3 +1,4 @@ +/* eslint-disable no-case-declarations */ import { readFile } from 'node:fs/promises'; import { join } from 'node:path'; import process, { cwd } from 'node:process'; @@ -220,7 +221,45 @@ export const getStaticProps: GetStaticProps = async ({ params }) => { } }; -const member = (props?: ApiItemJSON | undefined) => { +function resolveMember(packageName?: string | undefined, member?: SidebarLayoutProps['data']['member']) { + switch (member?.kind) { + case 'Class': { + const typedMember = member as ApiClassJSON; + return `?pkg=${packageName}&kind=${typedMember.kind}&name=${typedMember.name}&methods=${typedMember.methods.length}&props=${typedMember.properties.length}`; + } + + case 'Function': { + const typedMember = member as ApiFunctionJSON; + return `?pkg=${packageName}&kind=${typedMember.kind}&name=${typedMember.name}`; + } + + case 'Interface': { + const typedMember = member as ApiInterfaceJSON; + return `?pkg=${packageName}&kind=${typedMember.kind}&name=${typedMember.name}&methods=${typedMember.methods.length}&props=${typedMember.properties.length}`; + } + + case 'TypeAlias': { + const typedMember = member as ApiTypeAliasJSON; + return `?pkg=${packageName}&kind=${typedMember.kind}&name=${typedMember.name}`; + } + + case 'Variable': { + const typedMember = member as ApiVariableJSON; + return `?pkg=${packageName}&kind=${typedMember.kind}&name=${typedMember.name}`; + } + + case 'Enum': { + const typedMember = member as ApiEnumJSON; + return `?pkg=${packageName}&kind=${typedMember.kind}&name=${typedMember.name}&members=${typedMember.members.length}`; + } + + default: { + return `?pkg=${packageName}&kind=${member?.kind}&name=${member?.name}`; + } + } +} + +function member(props?: ApiItemJSON | undefined) { switch (props?.kind) { case 'Class': return ; @@ -237,7 +276,7 @@ const member = (props?: ApiItemJSON | undefined) => { default: return
Cannot render that item type
; } -}; +} export default function SlugPage(props: Partial) { const router = useRouter(); @@ -249,6 +288,10 @@ export default function SlugPage(props: Partial `${props.packageName ?? 'discord.js'}${props.data?.member?.name ? ` | ${props.data.member.name}` : ''}`, [props.packageName, props.data?.member?.name], ); + const ogImage = useMemo( + () => resolveMember(props.packageName, props.data?.member), + [props.packageName, props.data?.member], + ); if (router.isFallback) { return null; @@ -268,6 +311,7 @@ export default function SlugPage(props: Partial {name} + {member(props.data.member)}