Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions apps/website/src/components/ExcerptText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ export function ExcerptText({ 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' || meaning === 'var') href += `#${token.text}`;
else href += `/${meaning}/${token.text}`;
if (meaning === 'member' && path && 'parent' in path) {
href += `/enum/${path.parent}#${path.component}`;
} else if (meaning === 'type' || meaning === 'var') {
href += `#${token.text}`;
} else {
href += `/${meaning}/${token.text}`;
}

return (
<DocumentationLink key={`${token.text}-${idx}`} href={href}>
Expand Down
24 changes: 23 additions & 1 deletion apps/website/src/components/documentation/tsdoc/TSDoc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Link from 'next/link';
import { Fragment, useCallback, type ReactNode } from 'react';
import { DocumentationLink } from '~/components/DocumentationLink';
import { BuiltinDocumentationLinks } from '~/util/builtinDocumentationLinks';
import { DISCORD_API_TYPES_DOCS_URL } from '~/util/constants';
import { ItemLink } from '../../ItemLink';
import { SyntaxHighlighter } from '../../SyntaxHighlighter';
import { resolveCanonicalReference, resolveItemURI } from '../util';
Expand All @@ -32,7 +33,6 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
return <Fragment key={idx} />;
case DocNodeKind.LinkTag: {
const { codeDestination, urlDestination, linkText } = tsdoc as DocLinkTag;

if (codeDestination) {
if (
!codeDestination.importPath &&
Expand All @@ -56,6 +56,28 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:

if (!foundItem && !resolved) return null;

if (resolved && resolved.package === 'discord-api-types') {
const { displayName, kind, members, containerKey } = resolved.item;
let href = DISCORD_API_TYPES_DOCS_URL;

// dapi-types doesn't have routes for class members
// so we can assume this member is for an enum
if (kind === 'enum' && members?.[0]) {
href += `/enum/${displayName}#${members[0].displayName}`;
} else if (kind === 'type' || kind === 'var') {
href += `#${displayName}`;
} else {
href += `/${kind}/${displayName}`;
}

return (
<DocumentationLink key={`${containerKey}-${idx}`} href={href}>
{displayName}
{members?.map((member) => `.${member.displayName}`).join('') ?? ''}
</DocumentationLink>
);
}

return (
<ItemLink
className="rounded font-mono text-blurple outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
Expand Down
73 changes: 34 additions & 39 deletions apps/website/src/components/documentation/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,36 @@ import { resolveMembers } from '~/util/members';
import { resolveParameters } from '~/util/model';
import type { TableOfContentsSerialized } from '../TableOfContentItems';

export type ApiItemLike = {
[K in keyof ApiItem]?: K extends 'displayName' | 'kind'
? ApiItem[K]
: K extends 'parent'
? ApiItemLike | undefined
: ApiItem[K] | undefined;
};
export interface ApiItemLike {
containerKey?: string;
displayName: string;
kind: string;
members?: readonly ApiItemLike[];
parent?: ApiItemLike | undefined;
}

interface ResolvedCanonicalReference {
item: ApiItemLike;
package: string | undefined;
}

const kindToMeaning = new Map([
[ApiItemKind.CallSignature, Meaning.CallSignature],
[ApiItemKind.Class, Meaning.Class],
[ApiItemKind.ConstructSignature, Meaning.ConstructSignature],
[ApiItemKind.Constructor, Meaning.Constructor],
[ApiItemKind.Enum, Meaning.Enum],
[ApiItemKind.Event, Meaning.Event],
[ApiItemKind.Function, Meaning.Function],
[ApiItemKind.IndexSignature, Meaning.IndexSignature],
[ApiItemKind.Interface, Meaning.Interface],
[ApiItemKind.Property, Meaning.Member],
[ApiItemKind.Namespace, Meaning.Namespace],
[ApiItemKind.None, Meaning.ComplexType],
[ApiItemKind.TypeAlias, Meaning.TypeAlias],
[ApiItemKind.Variable, Meaning.Variable],
]);

export function hasProperties(item: ApiItemContainerMixin) {
return resolveMembers(item, memberPredicate).some(
({ item: member }) => member.kind === ApiItemKind.Property || member.kind === ApiItemKind.PropertySignature,
Expand Down Expand Up @@ -83,47 +100,25 @@ export function resolveCanonicalReference(
return {
package: canonicalReference.packageName?.replace('@discordjs/', ''),
item: {
kind: member.selector!.selector as ApiItemKind,
kind: member.selector!.selector,
displayName: member.memberIdentifier!.identifier,
containerKey: `|${member.selector!.selector}|${member.memberIdentifier!.identifier}`,
members: canonicalReference.memberReferences
.slice(1)
.map((member) => ({ kind: member.kind, displayName: member.memberIdentifier!.identifier! })),
},
};
}

return null;
}

function mapMeaningToKind(meaning: Meaning): ApiItemKind {
switch (meaning) {
case Meaning.CallSignature:
return ApiItemKind.CallSignature;
case Meaning.Class:
return ApiItemKind.Class;
case Meaning.ComplexType:
throw new Error('Not a valid canonicalReference: Meaning.ComplexType');
case Meaning.ConstructSignature:
return ApiItemKind.ConstructSignature;
case Meaning.Constructor:
return ApiItemKind.Constructor;
case Meaning.Enum:
return ApiItemKind.Enum;
case Meaning.Event:
return ApiItemKind.Event;
case Meaning.Function:
return ApiItemKind.Function;
case Meaning.IndexSignature:
return ApiItemKind.IndexSignature;
case Meaning.Interface:
return ApiItemKind.Interface;
case Meaning.Member:
return ApiItemKind.Property;
case Meaning.Namespace:
return ApiItemKind.Namespace;
case Meaning.TypeAlias:
return ApiItemKind.TypeAlias;
case Meaning.Variable:
return ApiItemKind.Variable;
}
export function mapMeaningToKind(meaning: Meaning): ApiItemKind {
return [...kindToMeaning.entries()].find((mapping) => mapping[1] === meaning)?.[0] ?? ApiItemKind.None;
}

export function mapKindToMeaning(kind: ApiItemKind): Meaning {
return kindToMeaning.get(kind) ?? Meaning.Variable;
}

export function memberPredicate(
Expand Down
Loading