Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(website): discord-api-types links, URL links and some minor doc issues #9990

Merged
merged 10 commits into from
Nov 22, 2023
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