mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-11 17:13:31 +01:00
feat: mainlib docs on new website (#9930)
* fix(ExceptText): don't display import("d..-types/v10"). in return type
* Squashed 'packages/api-extractor-model/' content from commit 39ecb196c
git-subtree-dir: packages/api-extractor-model
git-subtree-split: 39ecb196ca210bdf84ba6c9cadb1bb93571849d7
* Squashed 'packages/api-extractor/' content from commit 341ad6c51
git-subtree-dir: packages/api-extractor
git-subtree-split: 341ad6c51b01656d4f73b74ad4bdb3095f9262c4
* feat(api-extractor): add api-extractor and -model
* fix: package.json docs script
* fix(SourcLink): use <> instead of function syntax
* fix: make packages private
* fix: rest params showing in docs, added labels
* fix: missed two files
* feat: merge docs.json from docgen and docs.api.json
* fix: cpy-cli & pnpm-lock
* fix: increase icon size
* fix: icon size again
* feat: run both docs on mainlib
* chore: website fixes
* fix: more website fixes
* fix: tests and dev database script
* chore: comment out old docs
* fix: increase max fetch cache
* fix: env should always be a string
* fix: try to reapply patches
* fix: remove prepare for docgen
* fix: temporary cosmetic fixes
* fix: horizontal scroll
* feat: generate index for new docs
---------
Co-authored-by: Noel <buechler.noel@outlook.com>
This commit is contained in:
@@ -23,7 +23,7 @@ export async function fetchVersions(packageName: string): Promise<string[]> {
|
||||
return rows.map((row) => row.version);
|
||||
}
|
||||
|
||||
export async function fetchModelJSON(packageName: string, version: string): Promise<unknown> {
|
||||
export async function fetchModelJSON(packageName: string, version: string): Promise<unknown | null> {
|
||||
if (process.env.NEXT_PUBLIC_LOCAL_DEV) {
|
||||
const res = await readFile(
|
||||
join(process.cwd(), '..', '..', 'packages', packageName, 'docs', 'docs.api.json'),
|
||||
|
||||
@@ -32,9 +32,15 @@ import { findMember } from '~/util/model';
|
||||
|
||||
async function fetchHeadMember({ package: packageName, version, item }: ItemRouteParams) {
|
||||
const modelJSON = await fetchModelJSON(packageName, version);
|
||||
|
||||
if (!modelJSON) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const model = addPackageToModel(new ApiModel(), modelJSON);
|
||||
const pkg = model.tryGetPackageByName(packageName);
|
||||
const entry = pkg?.entryPoints[0];
|
||||
|
||||
if (!entry) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -88,7 +94,11 @@ export async function generateMetadata({ params }: { params: ItemRouteParams })
|
||||
const searchParams = resolveMemberSearchParams(params.package, member);
|
||||
url.search = searchParams.toString();
|
||||
const ogImage = url.toString();
|
||||
const description = tryResolveSummaryText(member as ApiDeclaredItem);
|
||||
let description;
|
||||
|
||||
if (member) {
|
||||
description = tryResolveSummaryText(member as ApiDeclaredItem);
|
||||
}
|
||||
|
||||
return {
|
||||
title: name,
|
||||
|
||||
@@ -4,7 +4,7 @@ import dynamic from 'next/dynamic';
|
||||
import { notFound } from 'next/navigation';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { fetchModelJSON, fetchVersions } from '~/app/docAPI';
|
||||
import { Banner } from '~/components/Banner';
|
||||
// import { Banner } from '~/components/Banner';
|
||||
import { CmdKDialog } from '~/components/CmdK';
|
||||
import { Nav } from '~/components/Nav';
|
||||
import type { SidebarSectionItemData } from '~/components/Sidebar';
|
||||
@@ -46,6 +46,11 @@ function serializeIntoSidebarItemData(item: ApiItem): SidebarSectionItemData {
|
||||
|
||||
export default async function PackageLayout({ children, params }: PropsWithChildren<{ params: VersionRouteParams }>) {
|
||||
const modelJSON = await fetchModelJSON(params.package, params.version);
|
||||
|
||||
if (!modelJSON) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const model = addPackageToModel(new ApiModel(), modelJSON);
|
||||
|
||||
const pkg = model.tryGetPackageByName(params.package);
|
||||
@@ -72,7 +77,7 @@ export default async function PackageLayout({ children, params }: PropsWithChild
|
||||
|
||||
return (
|
||||
<Providers>
|
||||
<Banner className="mb-6" />
|
||||
{/* <Banner className="mb-6" /> */}
|
||||
<main className="mx-auto max-w-7xl px-4 lg:max-w-full">
|
||||
<Header />
|
||||
<div className="relative top-2.5 mx-auto max-w-7xl gap-6 lg:max-w-full lg:flex">
|
||||
|
||||
@@ -7,22 +7,12 @@ import { fetchVersions } from '~/app/docAPI';
|
||||
import { buttonVariants } from '~/styles/Button';
|
||||
import { PACKAGES } from '~/util/constants';
|
||||
|
||||
async function getData(pkg: string) {
|
||||
if (!PACKAGES.includes(pkg)) {
|
||||
export default async function Page({ params }: { params: { package: string } }) {
|
||||
if (!PACKAGES.includes(params.package)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const data = await fetchVersions(pkg);
|
||||
|
||||
if (!data.length) {
|
||||
throw new Error('Failed to fetch data');
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export default async function Page({ params }: { params: { package: string } }) {
|
||||
const data = await getData(params.package);
|
||||
const data = await fetchVersions(params.package);
|
||||
|
||||
return (
|
||||
<div className="mx-auto min-h-screen min-w-xs flex flex-col gap-8 px-4 py-6 sm:w-md lg:px-6 lg:py-6">
|
||||
|
||||
@@ -11,7 +11,7 @@ export default function Page() {
|
||||
<div className="mx-auto min-h-screen min-w-xs flex flex-col gap-8 px-4 py-6 sm:w-md lg:px-6 lg:py-6">
|
||||
<h1 className="text-2xl font-semibold">Select a package:</h1>
|
||||
<div className="flex flex-col gap-4">
|
||||
<a className={buttonVariants({ variant: 'secondary' })} href="https://old.discordjs.dev/#/docs/discord.js">
|
||||
{/* <a className={buttonVariants({ variant: 'secondary' })} href="https://old.discordjs.dev/#/docs/discord.js">
|
||||
<div className="flex grow flex-row place-content-between place-items-center gap-4">
|
||||
<div className="flex flex-row place-content-between place-items-center gap-4">
|
||||
<VscPackage size={25} />
|
||||
@@ -19,7 +19,7 @@ export default function Page() {
|
||||
</div>
|
||||
<VscArrowRight size={20} />
|
||||
</div>
|
||||
</a>
|
||||
</a> */}
|
||||
{PACKAGES.map((pkg, idx) => (
|
||||
<Link
|
||||
className={buttonVariants({ variant: 'secondary' })}
|
||||
|
||||
@@ -4,7 +4,7 @@ import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import vercelLogo from '~/assets/powered-by-vercel.svg';
|
||||
import workersLogo from '~/assets/powered-by-workers.png';
|
||||
import { Banner } from '~/components/Banner';
|
||||
// import { Banner } from '~/components/Banner';
|
||||
import { InstallButton } from '~/components/InstallButton';
|
||||
import { buttonVariants } from '~/styles/Button';
|
||||
import { DESCRIPTION } from '~/util/constants';
|
||||
@@ -12,7 +12,7 @@ import { DESCRIPTION } from '~/util/constants';
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<Banner />
|
||||
{/* <Banner /> */}
|
||||
<div className="mx-auto max-w-6xl flex flex-col place-items-center gap-24 px-8 pb-16 pt-12 lg:min-h-[calc(100vh_-_40px)] lg:place-content-center lg:py-10">
|
||||
<div className="flex flex-col place-items-center gap-10 lg:flex-row lg:gap-6">
|
||||
<div className="flex flex-col place-items-center gap-10 text-center">
|
||||
@@ -22,11 +22,11 @@ export default function Page() {
|
||||
</h1>
|
||||
<p className="my-6 leading-normal text-neutral-700 dark:text-neutral-300">{DESCRIPTION}</p>
|
||||
<div className="flex flex-wrap place-content-center gap-4 md:flex-row">
|
||||
<a className={buttonVariants()} href="https://old.discordjs.dev/#/docs" rel="noopener noreferrer">
|
||||
{/* <a className={buttonVariants()} href="https://old.discordjs.dev/#/docs" rel="noopener noreferrer">
|
||||
Docs
|
||||
</a>
|
||||
</a> */}
|
||||
<Link className={buttonVariants()} href={'/docs' as Route}>
|
||||
Module docs
|
||||
Docs
|
||||
</Link>
|
||||
<a
|
||||
className={buttonVariants({ variant: 'secondary' })}
|
||||
|
||||
@@ -22,6 +22,8 @@ export function ExcerptText({ model, excerpt }: ExcerptTextProps) {
|
||||
return (
|
||||
<span>
|
||||
{excerpt.spannedTokens.map((token, idx) => {
|
||||
// TODO: Real fix in api-extractor needed
|
||||
const text = token.text.replaceAll('\n', '').replaceAll(/\s{2}$/g, '');
|
||||
if (token.kind === ExcerptTokenKind.Reference) {
|
||||
const source = token.canonicalReference?.source;
|
||||
const symbol = token.canonicalReference?.symbol;
|
||||
@@ -32,12 +34,12 @@ export function ExcerptText({ model, excerpt }: ExcerptTextProps) {
|
||||
// dapi-types doesn't have routes for class members
|
||||
// so we can assume this member is for an enum
|
||||
if (meaning === 'member' && path && 'parent' in path) href += `/enum/${path.parent}#${path.component}`;
|
||||
else if (meaning === 'type') href += `#${token.text}`;
|
||||
else href += `/${meaning}/${token.text}`;
|
||||
else if (meaning === 'type') href += `#${text}`;
|
||||
else href += `/${meaning}/${text}`;
|
||||
|
||||
return (
|
||||
<a className="text-blurple" href={href} key={idx} rel="external noreferrer noopener" target="_blank">
|
||||
{token.text}
|
||||
{text}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@@ -45,7 +47,7 @@ export function ExcerptText({ model, excerpt }: ExcerptTextProps) {
|
||||
const item = model.resolveDeclarationReference(token.canonicalReference!, model).resolvedApiItem;
|
||||
|
||||
if (!item) {
|
||||
return token.text;
|
||||
return text;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -55,12 +57,12 @@ export function ExcerptText({ model, excerpt }: ExcerptTextProps) {
|
||||
key={`${item.displayName}-${item.containerKey}-${idx}`}
|
||||
packageName={item.getAssociatedPackage()?.displayName.replace('@discordjs/', '')}
|
||||
>
|
||||
{token.text}
|
||||
{text}
|
||||
</ItemLink>
|
||||
);
|
||||
}
|
||||
|
||||
return token.text.replace(/import\("discord-api-types(?:\/v\d+)?"\)\./, '');
|
||||
return text.replace(/import\("discord-api-types(?:\/v\d+)?"\)\./, '');
|
||||
})}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -15,18 +15,18 @@ export default function PackageSelect() {
|
||||
const packageMenu = useMenuState({ gutter: 8, sameWidth: true, fitViewport: true });
|
||||
|
||||
const packageMenuItems = useMemo(
|
||||
() => [
|
||||
<a href="https://old.discordjs.dev/#/docs/discord.js" key="discord.js">
|
||||
<MenuItem
|
||||
className="my-0.5 rounded bg-white p-3 text-sm outline-none active:bg-light-800 dark:bg-dark-600 hover:bg-light-700 focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-400 dark:hover:bg-dark-500"
|
||||
id="discord-js"
|
||||
onClick={() => packageMenu.setOpen(false)}
|
||||
state={packageMenu}
|
||||
>
|
||||
discord.js
|
||||
</MenuItem>
|
||||
</a>,
|
||||
...PACKAGES.map((pkg, idx) => (
|
||||
() =>
|
||||
// <a href="https://old.discordjs.dev/#/docs/discord.js" key="discord.js">
|
||||
// <MenuItem
|
||||
// className="my-0.5 rounded bg-white p-3 text-sm outline-none active:bg-light-800 dark:bg-dark-600 hover:bg-light-700 focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-400 dark:hover:bg-dark-500"
|
||||
// id="discord-js"
|
||||
// onClick={() => packageMenu.setOpen(false)}
|
||||
// state={packageMenu}
|
||||
// >
|
||||
// discord.js
|
||||
// </MenuItem>
|
||||
// </a>,
|
||||
PACKAGES.map((pkg, idx) => (
|
||||
<Link href={`/docs/packages/${pkg}/main`} key={`${pkg}-${idx}`}>
|
||||
<MenuItem
|
||||
className="my-0.5 rounded bg-white p-3 text-sm outline-none active:bg-light-800 dark:bg-dark-600 hover:bg-light-700 focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-400 dark:hover:bg-dark-500"
|
||||
@@ -38,7 +38,6 @@ export default function PackageSelect() {
|
||||
</MenuItem>
|
||||
</Link>
|
||||
)),
|
||||
],
|
||||
[packageMenu],
|
||||
);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ export function Property({
|
||||
</CodeHeading>
|
||||
</div>
|
||||
{hasSummary || inheritedFrom ? (
|
||||
<div className="mb-4 flex flex-col gap-4">
|
||||
<div className="mb-4 w-full flex flex-col gap-4">
|
||||
{item.tsdocComment ? <TSDoc item={item} tsdoc={item.tsdocComment} /> : null}
|
||||
{inheritedFrom ? <InheritanceText parent={inheritedFrom} /> : null}
|
||||
{children}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { VscListSelection } from '@react-icons/all-files/vsc/VscListSelection';
|
||||
import { VscSymbolEvent } from '@react-icons/all-files/vsc/VscSymbolEvent';
|
||||
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
||||
import { VscSymbolProperty } from '@react-icons/all-files/vsc/VscSymbolProperty';
|
||||
import { useMemo } from 'react';
|
||||
@@ -16,7 +17,15 @@ export interface TableOfContentsSerializedProperty {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type TableOfContentsSerialized = TableOfContentsSerializedMethod | TableOfContentsSerializedProperty;
|
||||
export interface TableOfContentsSerializedEvent {
|
||||
kind: 'Event';
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type TableOfContentsSerialized =
|
||||
| TableOfContentsSerializedEvent
|
||||
| TableOfContentsSerializedMethod
|
||||
| TableOfContentsSerializedProperty;
|
||||
|
||||
export interface TableOfContentsItemProps {
|
||||
readonly serializedMembers: TableOfContentsSerialized[];
|
||||
@@ -57,6 +66,19 @@ export function TableOfContentsMethodItem({ method }: { readonly method: TableOf
|
||||
);
|
||||
}
|
||||
|
||||
export function TableOfContentsEventItem({ event }: { readonly event: TableOfContentsSerializedEvent }) {
|
||||
return (
|
||||
<a
|
||||
className="ml-[10px] border-l border-light-800 p-[5px] pl-6.5 text-sm outline-none focus:border-0 dark:border-dark-100 focus:rounded active:bg-light-800 hover:bg-light-700 focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-100 dark:hover:bg-dark-200"
|
||||
href={`#${event.name}`}
|
||||
key={`${event.name}-${event.kind}`}
|
||||
title={event.name}
|
||||
>
|
||||
<span className="line-clamp-1">{event.name}</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export function TableOfContentItems({ serializedMembers }: TableOfContentsItemProps) {
|
||||
const propertyItems = useMemo(
|
||||
() =>
|
||||
@@ -85,6 +107,14 @@ export function TableOfContentItems({ serializedMembers }: TableOfContentsItemPr
|
||||
[serializedMembers],
|
||||
);
|
||||
|
||||
const eventItems = useMemo(
|
||||
() =>
|
||||
serializedMembers
|
||||
.filter((member): member is TableOfContentsSerializedEvent => member.kind === 'Event')
|
||||
.map((event, idx) => <TableOfContentsEventItem key={`${event.name}-${event.kind}-${idx}`} event={event} />),
|
||||
[serializedMembers],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col break-all p-3 pb-8">
|
||||
<div className="ml-2 mt-4 flex flex-row gap-2">
|
||||
@@ -92,6 +122,17 @@ export function TableOfContentItems({ serializedMembers }: TableOfContentsItemPr
|
||||
<span className="font-semibold">Contents</span>
|
||||
</div>
|
||||
<div className="ml-2 mt-5.5 flex flex-col gap-2">
|
||||
{eventItems.length ? (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-row place-items-center gap-4">
|
||||
<VscSymbolEvent size={20} />
|
||||
<div className="p-3 pl-0">
|
||||
<span className="font-semibold">Properties</span>
|
||||
</div>
|
||||
</div>
|
||||
{eventItems}
|
||||
</div>
|
||||
) : null}
|
||||
{propertyItems.length ? (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-row place-items-center gap-4">
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import type { ApiDeclaredItem, ApiItemContainerMixin } from '@discordjs/api-extractor-model';
|
||||
import { EventsSection } from './section/EventsSection';
|
||||
import { MethodsSection } from './section/MethodsSection';
|
||||
import { PropertiesSection } from './section/PropertiesSection';
|
||||
import { hasProperties, hasMethods } from './util';
|
||||
import { hasEvents, hasProperties, hasMethods } from './util';
|
||||
|
||||
export function Members({ item }: { readonly item: ApiDeclaredItem & ApiItemContainerMixin }) {
|
||||
return (
|
||||
<>
|
||||
{hasEvents(item) ? <EventsSection item={item} /> : null}
|
||||
{hasProperties(item) ? <PropertiesSection item={item} /> : null}
|
||||
{hasMethods(item) ? <MethodsSection item={item} /> : null}
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import {
|
||||
ApiItemKind,
|
||||
type ApiEvent,
|
||||
type ApiItem,
|
||||
type ApiItemContainerMixin,
|
||||
type ApiDeclaredItem,
|
||||
} from '@discordjs/api-extractor-model';
|
||||
import { VscSymbolEvent } from '@react-icons/all-files/vsc/VscSymbolEvent';
|
||||
import { Fragment, useMemo } from 'react';
|
||||
import { Event } from '~/components/model/Event';
|
||||
import { resolveMembers } from '~/util/members';
|
||||
import { DocumentationSection } from './DocumentationSection';
|
||||
|
||||
function isEventLike(item: ApiItem): item is ApiEvent {
|
||||
return item.kind === ApiItemKind.Event;
|
||||
}
|
||||
|
||||
export function EventsSection({ item }: { readonly item: ApiItemContainerMixin }) {
|
||||
const members = resolveMembers(item, isEventLike);
|
||||
|
||||
const eventItems = useMemo(
|
||||
() =>
|
||||
members.map((event, idx) => {
|
||||
return (
|
||||
<Fragment key={`${event.item.displayName}-${idx}`}>
|
||||
<Event
|
||||
inheritedFrom={event.inherited as ApiDeclaredItem & ApiItemContainerMixin}
|
||||
item={event.item as ApiEvent}
|
||||
/>
|
||||
<div className="border-t-2 border-light-900 dark:border-dark-100" />
|
||||
</Fragment>
|
||||
);
|
||||
}),
|
||||
[members],
|
||||
);
|
||||
|
||||
return (
|
||||
<DocumentationSection icon={<VscSymbolEvent size={20} />} padded title="Events">
|
||||
<div className="flex flex-col gap-4">{eventItems}</div>
|
||||
</DocumentationSection>
|
||||
);
|
||||
}
|
||||
@@ -32,7 +32,9 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
|
||||
const { codeDestination, urlDestination, linkText } = tsdoc as DocLinkTag;
|
||||
|
||||
if (codeDestination) {
|
||||
const foundItem = item.getAssociatedModel()?.resolveDeclarationReference(codeDestination, item)
|
||||
// TODO: Real fix in api-extractor needed
|
||||
const currentItem = item.getAssociatedPackage();
|
||||
const foundItem = item.getAssociatedModel()?.resolveDeclarationReference(codeDestination, currentItem)
|
||||
.resolvedApiItem;
|
||||
|
||||
if (!foundItem) return null;
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
ApiPropertySignature,
|
||||
ApiDocumentedItem,
|
||||
ApiParameterListMixin,
|
||||
ApiEvent,
|
||||
} from '@discordjs/api-extractor-model';
|
||||
import { METHOD_SEPARATOR, OVERLOAD_SEPARATOR } from '~/util/constants';
|
||||
import { resolveMembers } from '~/util/members';
|
||||
@@ -26,6 +27,10 @@ export function hasMethods(item: ApiItemContainerMixin) {
|
||||
);
|
||||
}
|
||||
|
||||
export function hasEvents(item: ApiItemContainerMixin) {
|
||||
return resolveMembers(item, memberPredicate).some(({ item: member }) => member.kind === ApiItemKind.Event);
|
||||
}
|
||||
|
||||
export function resolveItemURI(item: ApiItem): string {
|
||||
return !item.parent || item.parent.kind === ApiItemKind.EntryPoint
|
||||
? `${item.displayName}${OVERLOAD_SEPARATOR}${item.kind}`
|
||||
@@ -34,12 +39,13 @@ export function resolveItemURI(item: ApiItem): string {
|
||||
|
||||
export function memberPredicate(
|
||||
item: ApiItem,
|
||||
): item is ApiMethod | ApiMethodSignature | ApiProperty | ApiPropertySignature {
|
||||
): item is ApiEvent | ApiMethod | ApiMethodSignature | ApiProperty | ApiPropertySignature {
|
||||
return (
|
||||
item.kind === ApiItemKind.Property ||
|
||||
item.kind === ApiItemKind.PropertySignature ||
|
||||
item.kind === ApiItemKind.Method ||
|
||||
item.kind === ApiItemKind.MethodSignature
|
||||
item.kind === ApiItemKind.MethodSignature ||
|
||||
item.kind === ApiItemKind.Event
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,6 +56,11 @@ export function serializeMembers(clazz: ApiItemContainerMixin): TableOfContentsS
|
||||
kind: member.kind as 'Method' | 'MethodSignature',
|
||||
name: member.displayName,
|
||||
};
|
||||
} else if (member.kind === 'Event') {
|
||||
return {
|
||||
kind: member.kind as 'Event',
|
||||
name: member.displayName,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
kind: member.kind as 'Property' | 'PropertySignature',
|
||||
|
||||
39
apps/website/src/components/model/Event.tsx
Normal file
39
apps/website/src/components/model/Event.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { ApiDeclaredItem, ApiItemContainerMixin, ApiEvent } from '@discordjs/api-extractor-model';
|
||||
import { Badges } from '../Badges';
|
||||
import { CodeHeading } from '../CodeHeading';
|
||||
import { InheritanceText } from '../InheritanceText';
|
||||
import { ParameterTable } from '../ParameterTable';
|
||||
import { TSDoc } from '../documentation/tsdoc/TSDoc';
|
||||
import { parametersString } from '../documentation/util';
|
||||
|
||||
export function Event({
|
||||
item,
|
||||
inheritedFrom,
|
||||
}: {
|
||||
readonly inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
|
||||
readonly item: ApiEvent;
|
||||
}) {
|
||||
const hasSummary = Boolean(item.tsdocComment?.summarySection);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col scroll-mt-30 gap-4" id={item.displayName}>
|
||||
<div className="flex flex-col gap-2 md:-ml-9">
|
||||
<Badges item={item} />
|
||||
<CodeHeading
|
||||
href={`#${item.displayName}`}
|
||||
sourceURL={item.sourceLocation.fileUrl}
|
||||
sourceLine={item.sourceLocation.fileLine}
|
||||
>
|
||||
{`${item.name}(${parametersString(item)})`}
|
||||
</CodeHeading>
|
||||
</div>
|
||||
{hasSummary || inheritedFrom ? (
|
||||
<div className="mb-4 w-full flex flex-col gap-4">
|
||||
{item.tsdocComment ? <TSDoc item={item} tsdoc={item.tsdocComment} /> : null}
|
||||
{item.parameters.length ? <ParameterTable item={item} /> : null}
|
||||
{inheritedFrom ? <InheritanceText parent={inheritedFrom} /> : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import type {
|
||||
ApiDeclaredItem,
|
||||
ApiItemContainerMixin,
|
||||
ApiMethod,
|
||||
ApiMethodSignature,
|
||||
import {
|
||||
ApiItemKind,
|
||||
type ApiDeclaredItem,
|
||||
type ApiItemContainerMixin,
|
||||
type ApiMethod,
|
||||
type ApiMethodSignature,
|
||||
} from '@discordjs/api-extractor-model';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Fragment } from 'react';
|
||||
@@ -18,15 +19,23 @@ export function Method({
|
||||
readonly inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
|
||||
readonly method: ApiMethod | ApiMethodSignature;
|
||||
}) {
|
||||
if (method.getMergedSiblings().length > 1) {
|
||||
if (
|
||||
method
|
||||
.getMergedSiblings()
|
||||
.filter((sibling) => sibling.kind === ApiItemKind.Method || sibling.kind === ApiItemKind.MethodSignature).length >
|
||||
1
|
||||
) {
|
||||
// We have overloads, use the overload switcher, but render
|
||||
// each overload node on the server.
|
||||
const overloads = method.getMergedSiblings().map((sibling, idx) => (
|
||||
<Fragment key={`${sibling.displayName}-${idx}`}>
|
||||
<MethodHeader method={sibling as ApiMethod | ApiMethodSignature} />
|
||||
<MethodDocumentation method={sibling as ApiMethod | ApiMethodSignature} />
|
||||
</Fragment>
|
||||
));
|
||||
const overloads = method
|
||||
.getMergedSiblings()
|
||||
.filter((sibling) => sibling.kind === ApiItemKind.Method || sibling.kind === ApiItemKind.MethodSignature)
|
||||
.map((sibling, idx) => (
|
||||
<Fragment key={`${sibling.displayName}-${idx}`}>
|
||||
<MethodHeader method={sibling as ApiMethod | ApiMethodSignature} />
|
||||
<MethodDocumentation method={sibling as ApiMethod | ApiMethodSignature} />
|
||||
</Fragment>
|
||||
));
|
||||
|
||||
return <OverloadSwitcher methodName={method.displayName} overloads={overloads} />;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export function MethodDocumentation({ method, inheritedFrom }: MethodDocumentati
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mb-4 flex flex-col gap-4">
|
||||
<div className="mb-4 w-full flex flex-col gap-4">
|
||||
{method.tsdocComment ? <TSDoc item={method} tsdoc={method.tsdocComment} /> : null}
|
||||
{method.parameters.length ? <ParameterTable item={method} /> : null}
|
||||
{inheritedFrom && parent ? <InheritanceText parent={inheritedFrom} /> : null}
|
||||
|
||||
@@ -12,7 +12,7 @@ export function MethodHeader({ method }: { readonly method: ApiMethod | ApiMetho
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col scroll-mt-30" id={key}>
|
||||
<div className="w-full flex flex-col scroll-mt-30" id={key}>
|
||||
<div className="flex flex-col gap-2 md:-ml-9">
|
||||
<Badges item={method} />
|
||||
<CodeHeading
|
||||
|
||||
@@ -21,7 +21,7 @@ async function fetchLatestVersion(packageName: string) {
|
||||
]);
|
||||
|
||||
// @ts-expect-error: https://github.com/planetscale/database-js/issues/71
|
||||
return rows[0].data.at(1);
|
||||
return rows.map((row) => row.version).at(1);
|
||||
}
|
||||
|
||||
export default async function middleware(request: NextRequest) {
|
||||
@@ -35,9 +35,9 @@ export default async function middleware(request: NextRequest) {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
if (request.nextUrl.pathname.includes('discord.js')) {
|
||||
/* if (request.nextUrl.pathname.includes('discord.js')) {
|
||||
return NextResponse.redirect('https://old.discordjs.dev/#/docs/discord.js');
|
||||
}
|
||||
} */
|
||||
|
||||
if (PACKAGES.some((pkg) => request.nextUrl.pathname.includes(pkg))) {
|
||||
// eslint-disable-next-line prefer-named-capture-group
|
||||
@@ -52,5 +52,5 @@ export default async function middleware(request: NextRequest) {
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ['/docs', '/docs/packages/discord.js(.*)?', '/docs/packages/:package/stable/:member*'],
|
||||
matcher: ['/docs', /* '/docs/packages/discord.js(.*)?',*/ '/docs/packages/:package/stable/:member*'],
|
||||
};
|
||||
|
||||
@@ -4,17 +4,23 @@ import { TSDocConfiguration } from '@microsoft/tsdoc';
|
||||
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
|
||||
|
||||
export function addPackageToModel(model: ApiModel, data: any) {
|
||||
const tsdocConfiguration = new TSDocConfiguration();
|
||||
const tsdocConfigFile = TSDocConfigFile.loadFromObject(data.metadata.tsdocConfig);
|
||||
tsdocConfigFile.configureParser(tsdocConfiguration);
|
||||
let apiPackage: ApiPackage;
|
||||
if (data.metadata) {
|
||||
const tsdocConfiguration = new TSDocConfiguration();
|
||||
const tsdocConfigFile = TSDocConfigFile.loadFromObject(data.metadata.tsdocConfig);
|
||||
tsdocConfigFile.configureParser(tsdocConfiguration);
|
||||
|
||||
apiPackage = ApiItem.deserialize(data, {
|
||||
apiJsonFilename: '',
|
||||
toolPackage: data.metadata.toolPackage,
|
||||
toolVersion: data.metadata.toolVersion,
|
||||
versionToDeserialize: data.metadata.schemaVersion,
|
||||
tsdocConfiguration,
|
||||
}) as ApiPackage;
|
||||
} else {
|
||||
apiPackage = ApiItem.deserializeDocgen(data, 'discord.js') as ApiPackage;
|
||||
}
|
||||
|
||||
const apiPackage = ApiItem.deserialize(data, {
|
||||
apiJsonFilename: '',
|
||||
toolPackage: data.metadata.toolPackage,
|
||||
toolVersion: data.metadata.toolVersion,
|
||||
versionToDeserialize: data.metadata.schemaVersion,
|
||||
tsdocConfiguration,
|
||||
}) as ApiPackage;
|
||||
model.addMember(apiPackage);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const PACKAGES = [
|
||||
'discord.js',
|
||||
'brokers',
|
||||
'builders',
|
||||
'collection',
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ApiModel, ApiFunction } from '@discordjs/api-extractor-model';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { fetchModelJSON } from '~/app/docAPI';
|
||||
import { addPackageToModel } from './addPackageToModel';
|
||||
import { OVERLOAD_SEPARATOR, PACKAGES } from './constants';
|
||||
@@ -13,7 +12,7 @@ export interface ItemRouteParams {
|
||||
|
||||
export async function fetchMember({ package: packageName, version: branchName = 'main', item }: ItemRouteParams) {
|
||||
if (!PACKAGES.includes(packageName)) {
|
||||
notFound();
|
||||
return null;
|
||||
}
|
||||
|
||||
const model = new ApiModel();
|
||||
@@ -22,10 +21,19 @@ export async function fetchMember({ package: packageName, version: branchName =
|
||||
const modelJSONFiles = await Promise.all(PACKAGES.map(async (pkg) => fetchModelJSON(pkg, branchName)));
|
||||
|
||||
for (const modelJSONFile of modelJSONFiles) {
|
||||
if (!modelJSONFile) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addPackageToModel(model, modelJSONFile);
|
||||
}
|
||||
} else {
|
||||
const modelJSON = await fetchModelJSON(packageName, branchName);
|
||||
|
||||
if (!modelJSON) {
|
||||
return null;
|
||||
}
|
||||
|
||||
addPackageToModel(model, modelJSON);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
import type { DocSection } from '@microsoft/tsdoc';
|
||||
|
||||
export function findMemberByKey(model: ApiModel, packageName: string, containerKey: string) {
|
||||
const pkg = model.tryGetPackageByName(`@discordjs/${packageName}`)!;
|
||||
const pkg = model.tryGetPackageByName(packageName === 'discord.js' ? packageName : `@discordjs/${packageName}`)!;
|
||||
return (pkg.members[0] as ApiEntryPoint).tryGetMemberByKey(containerKey);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export function findMember(model: ApiModel, packageName: string, memberName: str
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const pkg = model.tryGetPackageByName(`@discordjs/${packageName}`)!;
|
||||
const pkg = model.tryGetPackageByName(packageName === 'discord.js' ? packageName : `@discordjs/${packageName}`)!;
|
||||
return pkg.entryPoints[0]?.findMembersByName(memberName)[0];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user