mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
fix(website): doc links to other packages (#9994)
* fix(website): doc links to other packages * fix: missing parameter * Apply suggestions from code review Co-authored-by: Almeida <almeidx@pm.me> --------- Co-authored-by: Almeida <almeidx@pm.me>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { Excerpt } from '@discordjs/api-extractor-model';
|
||||
import type { ApiPackage, Excerpt } from '@discordjs/api-extractor-model';
|
||||
import { ExcerptTokenKind } from '@discordjs/api-extractor-model';
|
||||
import { BuiltinDocumentationLinks } from '~/util/builtinDocumentationLinks';
|
||||
import { DISCORD_API_TYPES_DOCS_URL } from '~/util/constants';
|
||||
@@ -7,6 +7,11 @@ import { ItemLink } from './ItemLink';
|
||||
import { resolveCanonicalReference, resolveItemURI } from './documentation/util';
|
||||
|
||||
export interface ExcerptTextProps {
|
||||
/**
|
||||
* The package this excerpt is referenced from.
|
||||
*/
|
||||
readonly apiPackage: ApiPackage;
|
||||
|
||||
/**
|
||||
* The tokens to render.
|
||||
*/
|
||||
@@ -16,7 +21,7 @@ export interface ExcerptTextProps {
|
||||
/**
|
||||
* A component that renders excerpt tokens from an api item.
|
||||
*/
|
||||
export function ExcerptText({ excerpt }: ExcerptTextProps) {
|
||||
export function ExcerptText({ excerpt, apiPackage }: ExcerptTextProps) {
|
||||
return (
|
||||
<span>
|
||||
{excerpt.spannedTokens.map((token, idx) => {
|
||||
@@ -53,7 +58,9 @@ export function ExcerptText({ excerpt }: ExcerptTextProps) {
|
||||
);
|
||||
}
|
||||
|
||||
const resolved = token.canonicalReference ? resolveCanonicalReference(token.canonicalReference) : null;
|
||||
const resolved = token.canonicalReference
|
||||
? resolveCanonicalReference(token.canonicalReference, apiPackage)
|
||||
: null;
|
||||
|
||||
if (!resolved) {
|
||||
return token.text;
|
||||
@@ -65,6 +72,7 @@ export function ExcerptText({ excerpt }: ExcerptTextProps) {
|
||||
itemURI={resolveItemURI(resolved.item)}
|
||||
key={`${resolved.item.displayName}-${resolved.item.containerKey}-${idx}`}
|
||||
packageName={resolved.package}
|
||||
version={resolved.version}
|
||||
>
|
||||
{token.text}
|
||||
</ItemLink>
|
||||
|
||||
@@ -20,6 +20,11 @@ export interface ItemLinkProps<Route extends string> extends Omit<LinkProps<Rout
|
||||
|
||||
// TODO: This needs to be properly typed above but monkey-patching it for now.
|
||||
readonly title?: string | undefined;
|
||||
|
||||
/**
|
||||
* The version of the package the item belongs to.
|
||||
*/
|
||||
readonly version?: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,7 +42,7 @@ export function ItemLink<Route extends string>(props: PropsWithChildren<ItemLink
|
||||
throw new Error('ItemLink must be used inside a Next.js page. (e.g. /docs/packages/foo/main)');
|
||||
}
|
||||
|
||||
const { itemURI, packageName: pkgName, ...linkProps } = props;
|
||||
const { itemURI, packageName: pkgName, version: pkgVersion, ...linkProps } = props;
|
||||
|
||||
return <Link {...linkProps} href={`/docs/packages/${pkgName ?? packageName}/${version}/${itemURI}`} />;
|
||||
return <Link {...linkProps} href={`/docs/packages/${pkgName ?? packageName}/${pkgVersion ?? version}/${itemURI}`} />;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export function ParameterTable({ item }: { readonly item: ApiDocumentedItem & Ap
|
||||
() =>
|
||||
params.map((param) => ({
|
||||
Name: param.isRest ? `...${param.name}` : param.name,
|
||||
Type: <ExcerptText excerpt={param.parameterTypeExcerpt} />,
|
||||
Type: <ExcerptText excerpt={param.parameterTypeExcerpt} apiPackage={item.getAssociatedPackage()!} />,
|
||||
Optional: param.isOptional ? 'Yes' : 'No',
|
||||
Description: param.description ? <TSDoc item={item} tsdoc={param.description} /> : 'None',
|
||||
})),
|
||||
|
||||
@@ -32,7 +32,9 @@ export function Property({
|
||||
>
|
||||
{`${item.displayName}${item.isOptional ? '?' : ''}`}
|
||||
<span>:</span>
|
||||
{item.propertyTypeExcerpt.text ? <ExcerptText excerpt={item.propertyTypeExcerpt} /> : null}
|
||||
{item.propertyTypeExcerpt.text ? (
|
||||
<ExcerptText excerpt={item.propertyTypeExcerpt} apiPackage={item.getAssociatedPackage()!} />
|
||||
) : null}
|
||||
</CodeHeading>
|
||||
</div>
|
||||
{hasSummary || inheritedFrom ? (
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Excerpt } from '@discordjs/api-extractor-model';
|
||||
import type { ApiPackage, Excerpt } from '@discordjs/api-extractor-model';
|
||||
import { ExcerptText } from './ExcerptText';
|
||||
|
||||
export function SignatureText({ excerpt }: { readonly excerpt: Excerpt }) {
|
||||
export function SignatureText({ excerpt, apiPackage }: { readonly apiPackage: ApiPackage; readonly excerpt: Excerpt }) {
|
||||
return (
|
||||
<h4 className="break-all text-lg font-bold font-mono">
|
||||
<ExcerptText excerpt={excerpt} />
|
||||
<ExcerptText excerpt={excerpt} apiPackage={apiPackage} />
|
||||
</h4>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ export function TypeParamTable({ item }: { readonly item: ApiTypeParameterListMi
|
||||
() =>
|
||||
item.typeParameters.map((typeParam) => ({
|
||||
Name: typeParam.name,
|
||||
Constraints: <ExcerptText excerpt={typeParam.constraintExcerpt} />,
|
||||
Constraints: <ExcerptText excerpt={typeParam.constraintExcerpt} apiPackage={item.getAssociatedPackage()!} />,
|
||||
Optional: typeParam.isOptional ? 'Yes' : 'No',
|
||||
Default: <ExcerptText excerpt={typeParam.defaultTypeExcerpt} />,
|
||||
Default: <ExcerptText excerpt={typeParam.defaultTypeExcerpt} apiPackage={item.getAssociatedPackage()!} />,
|
||||
Description: typeParam.tsdocTypeParamBlock ? (
|
||||
<TSDoc item={item} tsdoc={typeParam.tsdocTypeParamBlock.content} />
|
||||
) : (
|
||||
|
||||
@@ -48,7 +48,7 @@ export function HierarchyText({
|
||||
<div className="flex flex-row place-items-center gap-4" key={`${type}-${idx}`}>
|
||||
<h3 className="text-xl font-bold">{type}</h3>
|
||||
<span className="break-all font-mono space-y-2">
|
||||
<ExcerptText excerpt={excerpt} />
|
||||
<ExcerptText excerpt={excerpt} apiPackage={item.getAssociatedPackage()!} />
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -52,7 +52,7 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
|
||||
|
||||
const declarationReference = item.getAssociatedModel()?.resolveDeclarationReference(codeDestination, item);
|
||||
const foundItem = declarationReference?.resolvedApiItem;
|
||||
const resolved = resolveCanonicalReference(codeDestination);
|
||||
const resolved = resolveCanonicalReference(codeDestination, item.getAssociatedPackage());
|
||||
|
||||
if (!foundItem && !resolved) return null;
|
||||
|
||||
@@ -84,6 +84,12 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
|
||||
itemURI={resolveItemURI(foundItem ?? resolved!.item)}
|
||||
key={idx}
|
||||
packageName={resolved?.package ?? item.getAssociatedPackage()?.displayName.replace('@discordjs/', '')}
|
||||
version={
|
||||
resolved?.package
|
||||
? // eslint-disable-next-line unicorn/better-regex
|
||||
item.getAssociatedPackage()?.dependencies?.[resolved.package]?.replace(/[~^]/, '')
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{linkText ?? foundItem?.displayName ?? resolved!.item.displayName}
|
||||
</ItemLink>
|
||||
|
||||
@@ -9,6 +9,7 @@ import type {
|
||||
ApiDocumentedItem,
|
||||
ApiParameterListMixin,
|
||||
ApiEvent,
|
||||
ApiPackage,
|
||||
} from '@discordjs/api-extractor-model';
|
||||
import type { DocDeclarationReference } from '@microsoft/tsdoc';
|
||||
import { SelectorKind } from '@microsoft/tsdoc';
|
||||
@@ -29,6 +30,7 @@ export interface ApiItemLike {
|
||||
interface ResolvedCanonicalReference {
|
||||
item: ApiItemLike;
|
||||
package: string | undefined;
|
||||
version: string | undefined;
|
||||
}
|
||||
|
||||
const kindToMeaning = new Map([
|
||||
@@ -72,6 +74,7 @@ export function resolveItemURI(item: ApiItemLike): string {
|
||||
|
||||
export function resolveCanonicalReference(
|
||||
canonicalReference: DeclarationReference | DocDeclarationReference,
|
||||
apiPackage: ApiPackage | undefined,
|
||||
): ResolvedCanonicalReference | null {
|
||||
if (
|
||||
'source' in canonicalReference &&
|
||||
@@ -89,6 +92,8 @@ export function resolveCanonicalReference(
|
||||
canonicalReference.symbol.meaning
|
||||
}|${canonicalReference.symbol.componentPath.component.toString()}`,
|
||||
},
|
||||
// eslint-disable-next-line unicorn/better-regex
|
||||
version: apiPackage?.dependencies?.[canonicalReference.source.packageName]?.replace(/[~^]/, ''),
|
||||
};
|
||||
else if (
|
||||
'memberReferences' in canonicalReference &&
|
||||
@@ -107,6 +112,8 @@ export function resolveCanonicalReference(
|
||||
.slice(1)
|
||||
.map((member) => ({ kind: member.kind, displayName: member.memberIdentifier!.identifier! })),
|
||||
},
|
||||
// eslint-disable-next-line unicorn/better-regex
|
||||
version: apiPackage?.dependencies?.[canonicalReference.packageName ?? '']?.replace(/[~^]/, ''),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ export function EnumMember({ member }: { readonly member: ApiEnumMember }) {
|
||||
>
|
||||
{member.name}
|
||||
<span>=</span>
|
||||
{member.initializerExcerpt ? <SignatureText excerpt={member.initializerExcerpt} /> : null}
|
||||
{member.initializerExcerpt ? (
|
||||
<SignatureText excerpt={member.initializerExcerpt} apiPackage={member.getAssociatedPackage()!} />
|
||||
) : null}
|
||||
</CodeHeading>
|
||||
{member.tsdocComment ? <TSDoc item={member} tsdoc={member.tsdocComment.summarySection} /> : null}
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@ export function MethodHeader({ method }: { readonly method: ApiMethod | ApiMetho
|
||||
>
|
||||
{`${method.name}(${parametersString(method)})`}
|
||||
<span>:</span>
|
||||
<ExcerptText excerpt={method.returnTypeExcerpt} />
|
||||
<ExcerptText excerpt={method.returnTypeExcerpt} apiPackage={method.getAssociatedPackage()!} />
|
||||
</CodeHeading>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user