mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor(website): use new metadata api instead of head.tsx (#9269)
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
import { createApiModel, tryResolveSummaryText } from '@discordjs/scripts';
|
||||
import type {
|
||||
ApiDeclaredItem,
|
||||
ApiEnum,
|
||||
ApiItem,
|
||||
ApiItemContainerMixin,
|
||||
ApiMethod,
|
||||
ApiMethodSignature,
|
||||
ApiProperty,
|
||||
ApiPropertySignature,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
||||
import type { ItemRouteParams } from './page';
|
||||
import { fetchModelJSON } from '~/app/docAPI';
|
||||
import { OVERLOAD_SEPARATOR } from '~/util/constants';
|
||||
import { findMember } from '~/util/model.server';
|
||||
|
||||
async function fetchMember({ package: packageName, version, item }: ItemRouteParams): Promise<ApiItem | undefined> {
|
||||
const modelJSON = await fetchModelJSON(packageName, version);
|
||||
const model = createApiModel(modelJSON);
|
||||
const pkg = model.tryGetPackageByName(packageName);
|
||||
const entry = pkg?.entryPoints[0];
|
||||
|
||||
if (!entry) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const [memberName] = decodeURIComponent(item).split(OVERLOAD_SEPARATOR);
|
||||
|
||||
return findMember(model, packageName, memberName);
|
||||
}
|
||||
|
||||
function resolveMemberSearchParams(packageName: string, member: ApiItem): URLSearchParams {
|
||||
const params = new URLSearchParams({
|
||||
pkg: packageName,
|
||||
kind: member?.kind,
|
||||
name: member?.displayName,
|
||||
});
|
||||
|
||||
switch (member?.kind) {
|
||||
case ApiItemKind.Interface:
|
||||
case ApiItemKind.Class: {
|
||||
const typedMember = member as ApiItemContainerMixin;
|
||||
|
||||
const properties = typedMember.members.filter((member) =>
|
||||
[ApiItemKind.Property, ApiItemKind.PropertySignature].includes(member.kind),
|
||||
) as (ApiProperty | ApiPropertySignature)[];
|
||||
const methods = typedMember.members.filter((member) =>
|
||||
[ApiItemKind.Method, ApiItemKind.Method].includes(member.kind),
|
||||
) as (ApiMethod | ApiMethodSignature)[];
|
||||
|
||||
params.append('methods', methods.length.toString());
|
||||
params.append('props', properties.length.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
case ApiItemKind.Enum: {
|
||||
const typedMember = member as ApiEnum;
|
||||
params.append('members', typedMember.members.length.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
export default async function Head({ params }: { params: ItemRouteParams }) {
|
||||
const member = (await fetchMember(params))!;
|
||||
const name = `discord.js${member?.displayName ? ` | ${member.displayName}` : ''}`;
|
||||
const ogTitle = `${params.package ?? 'discord.js'}${member?.displayName ? ` | ${member.displayName}` : ''}`;
|
||||
const searchParams = resolveMemberSearchParams(params.package, member);
|
||||
const url = new URL('https://discordjs.dev/api/og_model');
|
||||
url.search = searchParams.toString();
|
||||
const ogImage = url.toString();
|
||||
const description = tryResolveSummaryText(member as ApiDeclaredItem);
|
||||
|
||||
return (
|
||||
<>
|
||||
<title key="title">{name}</title>
|
||||
<meta content={description ?? ''} key="description" name="description" />
|
||||
<meta content={ogTitle} key="og_title" property="og:title" />
|
||||
<meta content={description ?? ''} key="og_description" property="og:description" />
|
||||
<meta content={ogImage} key="og_image" property="og:image" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -3,16 +3,23 @@ import { readFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
// eslint-disable-next-line n/prefer-global/process
|
||||
import process, { cwd } from 'node:process';
|
||||
import { createApiModel } from '@discordjs/scripts';
|
||||
import { createApiModel, tryResolveSummaryText } from '@discordjs/scripts';
|
||||
import type {
|
||||
ApiClass,
|
||||
ApiDeclaredItem,
|
||||
ApiEnum,
|
||||
ApiInterface,
|
||||
ApiItem,
|
||||
ApiItemContainerMixin,
|
||||
ApiMethod,
|
||||
ApiMethodSignature,
|
||||
ApiProperty,
|
||||
ApiPropertySignature,
|
||||
ApiTypeAlias,
|
||||
ApiVariable,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import { ApiFunction } from '@microsoft/api-extractor-model';
|
||||
import { ApiItemKind, ApiFunction } from '@microsoft/api-extractor-model';
|
||||
import type { Metadata } from 'next';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { fetchModelJSON } from '~/app/docAPI';
|
||||
import { Class } from '~/components/model/Class';
|
||||
@@ -30,6 +37,79 @@ export interface ItemRouteParams {
|
||||
version: string;
|
||||
}
|
||||
|
||||
async function fetchHeadMember({ package: packageName, version, item }: ItemRouteParams): Promise<ApiItem | undefined> {
|
||||
const modelJSON = await fetchModelJSON(packageName, version);
|
||||
const model = createApiModel(modelJSON);
|
||||
const pkg = model.tryGetPackageByName(packageName);
|
||||
const entry = pkg?.entryPoints[0];
|
||||
|
||||
if (!entry) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const [memberName] = decodeURIComponent(item).split(OVERLOAD_SEPARATOR);
|
||||
|
||||
return findMember(model, packageName, memberName);
|
||||
}
|
||||
|
||||
function resolveMemberSearchParams(packageName: string, member: ApiItem): URLSearchParams {
|
||||
const params = new URLSearchParams({
|
||||
pkg: packageName,
|
||||
kind: member?.kind,
|
||||
name: member?.displayName,
|
||||
});
|
||||
|
||||
switch (member?.kind) {
|
||||
case ApiItemKind.Interface:
|
||||
case ApiItemKind.Class: {
|
||||
const typedMember = member as ApiItemContainerMixin;
|
||||
|
||||
const properties = typedMember.members.filter((member) =>
|
||||
[ApiItemKind.Property, ApiItemKind.PropertySignature].includes(member.kind),
|
||||
) as (ApiProperty | ApiPropertySignature)[];
|
||||
const methods = typedMember.members.filter((member) =>
|
||||
[ApiItemKind.Method, ApiItemKind.Method].includes(member.kind),
|
||||
) as (ApiMethod | ApiMethodSignature)[];
|
||||
|
||||
params.append('methods', methods.length.toString());
|
||||
params.append('props', properties.length.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
case ApiItemKind.Enum: {
|
||||
const typedMember = member as ApiEnum;
|
||||
params.append('members', typedMember.members.length.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: { params: ItemRouteParams }): Promise<Metadata> {
|
||||
const member = (await fetchHeadMember(params))!;
|
||||
const name = `discord.js${member?.displayName ? ` | ${member.displayName}` : ''}`;
|
||||
const ogTitle = `${params.package ?? 'discord.js'}${member?.displayName ? ` | ${member.displayName}` : ''}`;
|
||||
const url = new URL('https://discordjs.dev/api/og_model');
|
||||
const searchParams = resolveMemberSearchParams(params.package, member);
|
||||
url.search = searchParams.toString();
|
||||
const ogImage = url.toString();
|
||||
const description = tryResolveSummaryText(member as ApiDeclaredItem);
|
||||
|
||||
return {
|
||||
title: name,
|
||||
description: description ?? 'Discord.js API Documentation',
|
||||
openGraph: {
|
||||
title: ogTitle,
|
||||
description: description ?? 'Discord.js API Documentation',
|
||||
images: ogImage,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams({ params: { package: packageName, version } }: { params: ItemRouteParams }) {
|
||||
const modelJSON = await fetchModelJSON(packageName, version);
|
||||
const model = createApiModel(modelJSON);
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { DESCRIPTION } from '~/util/constants';
|
||||
|
||||
export default function Head() {
|
||||
return (
|
||||
<>
|
||||
<link href="/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180" />
|
||||
<link href="/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png" />
|
||||
<link href="/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png" />
|
||||
<link href="/site.webmanifest" rel="manifest" />
|
||||
<link color="#090a16" href="/safari-pinned-tab.svg" rel="mask-icon" />
|
||||
<meta content="light dark" name="color-scheme" />
|
||||
<meta content="discord.js" name="apple-mobile-web-app-title" />
|
||||
<meta content="discord.js" name="application-name" />
|
||||
<meta content="#090a16" name="msapplication-TileColor" />
|
||||
<meta content={DESCRIPTION} key="description" name="description" />
|
||||
<meta content="discord.js" property="og:site_name" />
|
||||
<meta content="website" property="og:type" />
|
||||
<meta content="discord.js" key="og_title" property="og:title" />
|
||||
<meta content={DESCRIPTION} key="og_description" property="og:description" />
|
||||
<meta content="https://discordjs.dev/api/og" key="og_image" property="og:image" />
|
||||
<meta content="summary_large_image" name="twitter:card" />
|
||||
<meta content="@iCrawlToGo" name="twitter:creator" />
|
||||
<title key="title">discord.js</title>
|
||||
<meta content="minimum-scale=1, initial-scale=1, width=device-width" name="viewport" />
|
||||
<meta content="#5865f2" name="theme-color" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,66 @@ import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import vercelLogo from '../assets/powered-by-vercel.svg';
|
||||
import { SyntaxHighlighter } from '~/components/SyntaxHighlighter';
|
||||
import { CODE_EXAMPLE } from '~/util/constants';
|
||||
import { CODE_EXAMPLE, DESCRIPTION } from '~/util/constants';
|
||||
|
||||
export const metadata = {
|
||||
title: 'discord.js',
|
||||
description: DESCRIPTION,
|
||||
viewport: {
|
||||
minimumScale: 1,
|
||||
initialScale: 1,
|
||||
width: 'device-width',
|
||||
},
|
||||
icons: {
|
||||
other: [
|
||||
{
|
||||
url: '/favicon-32x32.png',
|
||||
sizes: '32x32',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
url: '/favicon-16x16.png',
|
||||
sizes: '16x16',
|
||||
type: 'image/png',
|
||||
},
|
||||
],
|
||||
apple: [
|
||||
'/apple-touch-icon.png',
|
||||
{
|
||||
url: '/safari-pinned-tab.svg',
|
||||
rel: 'mask-icon',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
manifest: '/site.webmanifest',
|
||||
|
||||
themeColor: '#5865f2',
|
||||
colorScheme: 'light dark',
|
||||
|
||||
appleWebApp: {
|
||||
title: 'discord.js',
|
||||
},
|
||||
|
||||
applicationName: 'discord.js',
|
||||
|
||||
openGraph: {
|
||||
siteName: 'discord.js',
|
||||
type: 'website',
|
||||
title: 'discord.js',
|
||||
description: DESCRIPTION,
|
||||
images: 'https://discordjs.dev/api/og',
|
||||
},
|
||||
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
creator: '@iCrawlToGo',
|
||||
},
|
||||
|
||||
other: {
|
||||
'msapplication-TileColor': '#090a16',
|
||||
},
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user