From a14e3cb61245196a7bf4ad824df52001b77eeddf Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Sun, 19 Nov 2023 20:37:33 +0100
Subject: [PATCH 1/8] fix(website): correctly link to discord-api-types in link
tags
---
.../components/documentation/tsdoc/TSDoc.tsx | 34 ++++-
.../src/components/documentation/util.ts | 57 ++++----
.../src/generators/ApiModelGenerator.ts | 125 +++++++++++-------
3 files changed, 133 insertions(+), 83 deletions(-)
diff --git a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
index a0a0854fbe1e..6525638cfa26 100644
--- a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
+++ b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
@@ -1,14 +1,23 @@
-import type { ApiItem } from '@discordjs/api-extractor-model';
-import type { DocComment, DocFencedCode, DocLinkTag, DocNode, DocNodeContainer, DocPlainText } from '@microsoft/tsdoc';
+import { type ApiItem, ApiItemKind } from '@discordjs/api-extractor-model';
+import type {
+ DocComment,
+ DocFencedCode,
+ DocInlineTag,
+ DocLinkTag,
+ DocNode,
+ DocNodeContainer,
+ DocPlainText,
+} from '@microsoft/tsdoc';
import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
import type { Route } from 'next';
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';
+import { mapKindToMeaning, resolveCanonicalReference, resolveItemURI } from '../util';
import { DefaultValueBlock, DeprecatedBlock, ExampleBlock, RemarksBlock, ReturnsBlock, SeeBlock } from './BlockComment';
export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc: DocNode }): JSX.Element {
@@ -32,7 +41,6 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
return ;
case DocNodeKind.LinkTag: {
const { codeDestination, urlDestination, linkText } = tsdoc as DocLinkTag;
-
if (codeDestination) {
if (
!codeDestination.importPath &&
@@ -56,6 +64,24 @@ 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 += `/${mapKindToMeaning(kind)}/${displayName}`;
+
+ return (
+
+ {displayName}
+ {members?.map((member) => `.${member.displayName}`).join('') ?? ''}
+
+ );
+ }
+
return (
member.kind === ApiItemKind.Property || member.kind === ApiItemKind.PropertySignature,
@@ -86,6 +103,9 @@ export function resolveCanonicalReference(
kind: member.selector!.selector as ApiItemKind,
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 })),
},
};
}
@@ -93,37 +113,12 @@ export function resolveCanonicalReference(
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];
+}
+
+export function mapKindToMeaning(kind: ApiItemKind): Meaning {
+ return kindToMeaning.get(kind);
}
export function memberPredicate(
diff --git a/packages/api-extractor/src/generators/ApiModelGenerator.ts b/packages/api-extractor/src/generators/ApiModelGenerator.ts
index 983ee49a9187..32f4c0ba712a 100644
--- a/packages/api-extractor/src/generators/ApiModelGenerator.ts
+++ b/packages/api-extractor/src/generators/ApiModelGenerator.ts
@@ -210,14 +210,7 @@ interface IProcessAstEntityContext {
parentDocgenJson?: DocgenContainerJson | undefined;
}
-const linkRegEx = /{@link\s(?\w+)#(?event:)?(?[\w()]+)(?\s[^}]*)?}/g;
-function fixLinkTags(input?: string): string | undefined {
- return input?.replaceAll(
- linkRegEx,
- (_match, _p1, _p2, _p3, _p4, _offset, _string, groups) =>
- `{@link ${groups.class}.${groups.prop}${groups.name ? ` |${groups.name}` : ''}}`,
- );
-}
+const linkRegEx = /{@link\s(?\w+)[#.](?event:)?(?[\w()]+)(?\s[^}]*)?}/g;
function filePathFromJson(meta: DocgenMetaJson): string {
return `${meta.path.slice('packages/discord.js/'.length)}/${meta.file}`;
@@ -243,6 +236,8 @@ export class ApiModelGenerator {
private readonly _referenceGenerator: DeclarationReferenceGenerator;
+ private readonly _jsDocJson: DocgenJson | undefined;
+
public constructor(collector: Collector) {
this._collector = collector;
this._apiModel = new ApiModel();
@@ -257,11 +252,11 @@ export class ApiModelGenerator {
public buildApiPackage(): ApiPackage {
const packageDocComment: tsdoc.DocComment | undefined = this._collector.workingPackage.tsdocComment;
- let jsDocJson: DocgenJson | undefined;
const jsDocFilepath = `${this._collector.extractorConfig.apiJsonFilePath.slice(0, -8)}json`;
if (existsSync(jsDocFilepath)) {
- jsDocJson = JsonFile.load(jsDocFilepath);
+ // @ts-expect-error assign value only when starting to build a new ApiPackage
+ this._jsDocJson = JsonFile.load(jsDocFilepath);
}
const apiPackage: ApiPackage = new ApiPackage({
@@ -284,7 +279,7 @@ export class ApiModelGenerator {
name: entity.nameForEmit!,
isExported: entity.exportedFromEntryPoint,
parentApiItem: apiEntryPoint,
- parentDocgenJson: jsDocJson,
+ parentDocgenJson: this._jsDocJson,
});
}
}
@@ -560,9 +555,9 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = parent?.construct
? this._tsDocParser.parseString(
- `/*+\n * ${fixLinkTags(parent.construct.description)}\n${
+ `/*+\n * ${this._fixLinkTags(parent.construct.description) ?? ''}\n${
parent.construct.params
- ?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`)
+ ?.map((param) => ` * @param ${param.name} - ${this._fixLinkTags(param.description) ?? ''}\n`)
.join('') ?? ''
} */`,
).docComment
@@ -646,10 +641,12 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description)}\n${jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
+ jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''
+ }${
jsDoc.deprecated
? ` * @deprecated ${
- typeof jsDoc.deprecated === 'string' ? fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
+ typeof jsDoc.deprecated === 'string' ? this._fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
}\n`
: ''
} */`,
@@ -718,9 +715,9 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = parent?.construct
? this._tsDocParser.parseString(
- `/*+\n * ${fixLinkTags(parent.construct.description)}\n${
+ `/*+\n * ${this._fixLinkTags(parent.construct.description) ?? ''}\n${
parent.construct.params
- ?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`)
+ ?.map((param) => ` * @param ${param.name} - ${this._fixLinkTags(param.description) ?? ''}\n`)
.join('') ?? ''
} */`,
).docComment
@@ -849,17 +846,18 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description)}\n${
- jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ??
- ''
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
+ jsDoc.params
+ ?.map((param) => ` * @param ${param.name} - ${this._fixLinkTags(param.description) ?? ''}\n`)
+ .join('') ?? ''
}${
jsDoc.returns?.length && !Array.isArray(jsDoc.returns[0])
- ? ` * @returns ${fixLinkTags(jsDoc.returns[0]!.description ?? '')}`
+ ? ` * @returns ${this._fixLinkTags(jsDoc.returns[0]!.description) ?? ''}`
: ''
}${
jsDoc.deprecated
? ` * @deprecated ${
- typeof jsDoc.deprecated === 'string' ? fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
+ typeof jsDoc.deprecated === 'string' ? this._fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
}\n`
: ''
} */`,
@@ -976,10 +974,12 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description)}\n${jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
+ jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''
+ }${
jsDoc.deprecated
? ` * @deprecated ${
- typeof jsDoc.deprecated === 'string' ? fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
+ typeof jsDoc.deprecated === 'string' ? this._fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
}\n`
: ''
} */`,
@@ -1046,20 +1046,20 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description)}\n${
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
jsDoc.params
- ?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`)
+ ?.map((param) => ` * @param ${param.name} - ${this._fixLinkTags(param.description) ?? ''}\n`)
.join('') ?? ''
}${
jsDoc.returns?.length && !Array.isArray(jsDoc.returns[0])
- ? ` * @returns ${fixLinkTags(jsDoc.returns[0]!.description ?? '')}`
+ ? ` * @returns ${this._fixLinkTags(jsDoc.returns[0]!.description) ?? ''}`
: ''
}${
jsDoc.examples?.map((example) => ` * @example\n * \`\`\`js\n * ${example}\n * \`\`\`\n`).join('') ?? ''
}${
jsDoc.deprecated
? ` * @deprecated ${
- typeof jsDoc.deprecated === 'string' ? fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
+ typeof jsDoc.deprecated === 'string' ? this._fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
}\n`
: ''
} */`,
@@ -1136,18 +1136,18 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description)}\n${
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
jsDoc.params
- ?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`)
+ ?.map((param) => ` * @param ${param.name} - ${this._fixLinkTags(param.description) ?? ''}\n`)
.join('') ?? ''
}${
jsDoc.returns?.length && !Array.isArray(jsDoc.returns[0])
- ? ` * @returns ${fixLinkTags(jsDoc.returns[0]!.description ?? '')}`
+ ? ` * @returns ${this._fixLinkTags(jsDoc.returns[0]!.description) ?? ''}`
: ''
}${
jsDoc.deprecated
? ` * @deprecated ${
- typeof jsDoc.deprecated === 'string' ? fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
+ typeof jsDoc.deprecated === 'string' ? this._fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
}\n`
: ''
} */`,
@@ -1253,12 +1253,12 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description)}\n${
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
'deprecated' in jsDoc && jsDoc.deprecated
? ` * @deprecated ${
- typeof jsDoc.deprecated === 'string' ? fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
+ typeof jsDoc.deprecated === 'string' ? this._fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
}\n`
: ''
} */`,
@@ -1328,10 +1328,14 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description)}\n${
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
- 'deprecated' in jsDoc && jsDoc.deprecated ? ` * @deprecated ${jsDoc.deprecated}\n` : ''
+ 'deprecated' in jsDoc && jsDoc.deprecated
+ ? ` * @deprecated ${
+ typeof jsDoc.deprecated === 'string' ? this._fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
+ }\n`
+ : ''
} */`,
).docComment
: apiItemMetadata.tsdocComment;
@@ -1396,13 +1400,17 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description) ?? ''}\n${
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
'params' in jsDoc
- ? jsDoc.params.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('')
+ ? jsDoc.params
+ .map((param) => ` * @param ${param.name} - ${this._fixLinkTags(param.description) ?? ''}\n`)
+ .join('')
: ''
}${
'returns' in jsDoc
- ? jsDoc.returns.map((ret) => ` * @returns ${Array.isArray(ret) ? '' : fixLinkTags(ret.description)}\n`)
+ ? jsDoc.returns.map(
+ (ret) => ` * @returns ${Array.isArray(ret) ? '' : this._fixLinkTags(ret.description) ?? ''}\n`,
+ )
: ''
} */`,
).docComment
@@ -1531,12 +1539,14 @@ export class ApiModelGenerator {
}
const docComment: tsdoc.DocComment | undefined = this._tsDocParser.parseString(
- `/**\n * ${fixLinkTags(jsDoc.description)}\n${
- jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ?? ''
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
+ jsDoc.params
+ ?.map((param) => ` * @param ${param.name} - ${this._fixLinkTags(param.description) ?? ''}\n`)
+ .join('') ?? ''
}${'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''}${
'deprecated' in jsDoc && jsDoc.deprecated
? ` * @deprecated ${
- typeof jsDoc.deprecated === 'string' ? fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
+ typeof jsDoc.deprecated === 'string' ? this._fixLinkTags(jsDoc.deprecated) : jsDoc.deprecated
}\n`
: ''
} */`,
@@ -1672,6 +1682,23 @@ export class ApiModelGenerator {
return sourceLocation;
}
+ private _fixLinkTags(input?: string): string | undefined {
+ return input?.replaceAll(linkRegEx, (_match, _p1, _p2, _p3, _p4, _offset, _string, groups) => {
+ const external = this._jsDocJson?.externals.find((external) => external.name === groups.class);
+ let target = groups.class;
+ const match = /discord-api-types-(?[^#]*?)(?:#|\/(?[^#/]*)\/)(?[^/}]*)}$/.exec(
+ external?.see?.[0] ?? '',
+ );
+ if (match) {
+ target = `discord-api-types#(${match.groups!.name}:${
+ /^v\d+$/.test(match.groups!.type!) ? match.groups!.kind : 'type'
+ })`;
+ }
+
+ return `{@link ${target}.${groups.prop}${groups.name ? ` |${groups.name}` : ''}}`;
+ });
+ }
+
private _mapVarType(typey: DocgenVarTypeJson): IExcerptToken[] {
const mapper = Array.isArray(typey) ? typey : typey.types ?? [];
const lookup: { [K in ts.SyntaxKind]?: string } = {
@@ -1729,9 +1756,9 @@ export class ApiModelGenerator {
isOptional: Boolean(prop.nullable),
isReadonly: Boolean(prop.readonly),
docComment: this._tsDocParser.parseString(
- `/**\n * ${prop.description}\n${prop.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${
- prop.readonly ? ' * @readonly\n' : ''
- } */`,
+ `/**\n * ${this._fixLinkTags(prop.description) ?? ''}\n${
+ prop.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''
+ }${prop.readonly ? ' * @readonly\n' : ''} */`,
).docComment,
excerptTokens: [
{
@@ -1820,11 +1847,13 @@ export class ApiModelGenerator {
: { startIndex: 0, endIndex: 0 },
typeParameters: [],
docComment: this._tsDocParser.parseString(
- `/**\n * ${method.description}\n${
- method.params?.map((param) => ` * @param ${param.name} - ${param.description}\n`).join('') ?? ''
+ `/**\n * ${this._fixLinkTags(method.description) ?? ''}\n${
+ method.params
+ ?.map((param) => ` * @param ${param.name} - ${this._fixLinkTags(param.description) ?? ''}\n`)
+ .join('') ?? ''
}${
method.returns?.length && !Array.isArray(method.returns[0])
- ? ` * @returns ${method.returns[0]!.description}`
+ ? ` * @returns ${this._fixLinkTags(method.returns[0]!.description) ?? ''}`
: ''
}${method.examples?.map((example) => ` * @example\n * \`\`\`js\n * ${example}\n * \`\`\`\n`).join('') ?? ''}${
method.deprecated
From 53b53578283cd7f2f8a1e1f49a9181bacec7c199 Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Sun, 19 Nov 2023 21:08:02 +0100
Subject: [PATCH 2/8] fix: url links and some minor doc issues
---
.../api-extractor/src/generators/ApiModelGenerator.ts | 11 ++++++-----
packages/discord.js/src/client/BaseClient.js | 2 +-
.../discord.js/src/client/voice/ClientVoiceManager.js | 2 +-
packages/discord.js/src/structures/Guild.js | 2 +-
packages/discord.js/src/util/Sweepers.js | 2 +-
5 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/packages/api-extractor/src/generators/ApiModelGenerator.ts b/packages/api-extractor/src/generators/ApiModelGenerator.ts
index 32f4c0ba712a..701b54ccd671 100644
--- a/packages/api-extractor/src/generators/ApiModelGenerator.ts
+++ b/packages/api-extractor/src/generators/ApiModelGenerator.ts
@@ -210,7 +210,8 @@ interface IProcessAstEntityContext {
parentDocgenJson?: DocgenContainerJson | undefined;
}
-const linkRegEx = /{@link\s(?\w+)[#.](?event:)?(?[\w()]+)(?\s[^}]*)?}/g;
+const linkRegEx =
+ /{@link\s(?:(?\w+)(?:[#.](?event:)?(?[\w()]+))?|(?https?:\/\/[^\s}]*))(?\s[^}]*)?}/g;
function filePathFromJson(meta: DocgenMetaJson): string {
return `${meta.path.slice('packages/discord.js/'.length)}/${meta.file}`;
@@ -1683,9 +1684,9 @@ export class ApiModelGenerator {
}
private _fixLinkTags(input?: string): string | undefined {
- return input?.replaceAll(linkRegEx, (_match, _p1, _p2, _p3, _p4, _offset, _string, groups) => {
- const external = this._jsDocJson?.externals.find((external) => external.name === groups.class);
- let target = groups.class;
+ return input?.replaceAll(linkRegEx, (_match, _p1, _p2, _p3, _p4, _p5, _offset, _string, groups) => {
+ let target = groups.class ?? groups.url;
+ const external = this._jsDocJson?.externals.find((external) => groups.class && external.name === groups.class);
const match = /discord-api-types-(?[^#]*?)(?:#|\/(?[^#/]*)\/)(?[^/}]*)}$/.exec(
external?.see?.[0] ?? '',
);
@@ -1695,7 +1696,7 @@ export class ApiModelGenerator {
})`;
}
- return `{@link ${target}.${groups.prop}${groups.name ? ` |${groups.name}` : ''}}`;
+ return `{@link ${target}${groups.prop ? `.${groups.prop}` : ''}${groups.name ? ` |${groups.name}` : ''}}`;
});
}
diff --git a/packages/discord.js/src/client/BaseClient.js b/packages/discord.js/src/client/BaseClient.js
index 8b1c261fab7e..8df5e549de3c 100644
--- a/packages/discord.js/src/client/BaseClient.js
+++ b/packages/discord.js/src/client/BaseClient.js
@@ -19,11 +19,11 @@ class BaseClient extends EventEmitter {
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
}
+ const defaultOptions = Options.createDefault();
/**
* The options the client was instantiated with
* @type {ClientOptions}
*/
- const defaultOptions = Options.createDefault();
this.options = {
...defaultOptions,
...options,
diff --git a/packages/discord.js/src/client/voice/ClientVoiceManager.js b/packages/discord.js/src/client/voice/ClientVoiceManager.js
index 192e7001a4bc..55b0d830ed38 100644
--- a/packages/discord.js/src/client/voice/ClientVoiceManager.js
+++ b/packages/discord.js/src/client/voice/ClientVoiceManager.js
@@ -16,7 +16,7 @@ class ClientVoiceManager {
Object.defineProperty(this, 'client', { value: client });
/**
- * Maps guild ids to voice adapters created for use with @discordjs/voice.
+ * Maps guild ids to voice adapters created for use with `@discordjs/voice`.
* @type {Map}
*/
this.adapters = new Map();
diff --git a/packages/discord.js/src/structures/Guild.js b/packages/discord.js/src/structures/Guild.js
index da3843855b4d..51a26750a751 100644
--- a/packages/discord.js/src/structures/Guild.js
+++ b/packages/discord.js/src/structures/Guild.js
@@ -1405,7 +1405,7 @@ class Guild extends AnonymousGuild {
}
/**
- * The voice state adapter for this guild that can be used with @discordjs/voice to play audio in voice
+ * The voice state adapter for this guild that can be used with `@discordjs/voice` to play audio in voice
* and stage channels.
* @type {Function}
* @readonly
diff --git a/packages/discord.js/src/util/Sweepers.js b/packages/discord.js/src/util/Sweepers.js
index 3cc910838c2d..3402f2fe9aa6 100644
--- a/packages/discord.js/src/util/Sweepers.js
+++ b/packages/discord.js/src/util/Sweepers.js
@@ -8,7 +8,7 @@ const { DiscordjsTypeError, ErrorCodes } = require('../errors');
/**
* @typedef {Function} GlobalSweepFilter
* @returns {?Function} Return `null` to skip sweeping, otherwise a function passed to `sweep()`,
- * See {@link [Collection#sweep](https://discord.js.org/docs/packages/collection/stable/Collection:Class#sweep)}
+ * See {@link https://discord.js.org/docs/packages/collection/stable/Collection:Class#sweep Collection#sweep}
* for the definition of this function.
*/
From 7110365ae107c493d2bfd440cc49fc78aed2cd2d Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Sun, 19 Nov 2023 21:11:54 +0100
Subject: [PATCH 3/8] fix: unneeded import
---
.../src/components/documentation/tsdoc/TSDoc.tsx | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
index 6525638cfa26..4f2ab824c2d6 100644
--- a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
+++ b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
@@ -1,13 +1,5 @@
import { type ApiItem, ApiItemKind } from '@discordjs/api-extractor-model';
-import type {
- DocComment,
- DocFencedCode,
- DocInlineTag,
- DocLinkTag,
- DocNode,
- DocNodeContainer,
- DocPlainText,
-} from '@microsoft/tsdoc';
+import type { DocComment, DocFencedCode, DocLinkTag, DocNode, DocNodeContainer, DocPlainText } from '@microsoft/tsdoc';
import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
import type { Route } from 'next';
import Link from 'next/link';
From 3269bb7b6e0899f6458a66e67baea6caa361c107 Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Sun, 19 Nov 2023 21:20:04 +0100
Subject: [PATCH 4/8] fix: another unneccessary import
---
apps/website/src/components/documentation/tsdoc/TSDoc.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
index 4f2ab824c2d6..906c5a0171f4 100644
--- a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
+++ b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
@@ -1,4 +1,4 @@
-import { type ApiItem, ApiItemKind } from '@discordjs/api-extractor-model';
+import type { ApiItem } from '@discordjs/api-extractor-model';
import type { DocComment, DocFencedCode, DocLinkTag, DocNode, DocNodeContainer, DocPlainText } from '@microsoft/tsdoc';
import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
import type { Route } from 'next';
From 2ed577d9c29fd2408dd405f0d5630e18bfd8f00d Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Sun, 19 Nov 2023 21:34:59 +0100
Subject: [PATCH 5/8] fix: several linting issues
---
.../components/documentation/tsdoc/TSDoc.tsx | 6 +++---
.../src/components/documentation/util.ts | 20 +++++++++++--------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
index 906c5a0171f4..4253f2129c4d 100644
--- a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
+++ b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
@@ -9,7 +9,7 @@ import { BuiltinDocumentationLinks } from '~/util/builtinDocumentationLinks';
import { DISCORD_API_TYPES_DOCS_URL } from '~/util/constants';
import { ItemLink } from '../../ItemLink';
import { SyntaxHighlighter } from '../../SyntaxHighlighter';
-import { mapKindToMeaning, resolveCanonicalReference, resolveItemURI } from '../util';
+import { resolveCanonicalReference, resolveItemURI } from '../util';
import { DefaultValueBlock, DeprecatedBlock, ExampleBlock, RemarksBlock, ReturnsBlock, SeeBlock } from './BlockComment';
export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc: DocNode }): JSX.Element {
@@ -62,9 +62,9 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
// 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}`;
+ if (kind === 'enum' && members?.[0]) href += `/enum/${displayName}#${members[0].displayName}`;
else if (kind === 'type' || kind === 'var') href += `#${displayName}`;
- else href += `/${mapKindToMeaning(kind)}/${displayName}`;
+ else href += `/${kind}/${displayName}`;
return (
diff --git a/apps/website/src/components/documentation/util.ts b/apps/website/src/components/documentation/util.ts
index 95820a2f929e..9c2f233db568 100644
--- a/apps/website/src/components/documentation/util.ts
+++ b/apps/website/src/components/documentation/util.ts
@@ -19,11 +19,15 @@ import { resolveParameters } from '~/util/model';
import type { TableOfContentsSerialized } from '../TableOfContentItems';
export type ApiItemLike = {
- [K in keyof ApiItem]?: K extends 'displayName' | 'kind'
+ [K in keyof ApiItem]?: K extends 'displayName'
? ApiItem[K]
- : K extends 'parent'
- ? ApiItemLike | undefined
- : ApiItem[K] | undefined;
+ : K extends 'kind'
+ ? string
+ : K extends 'parent'
+ ? ApiItemLike | undefined
+ : K extends 'members'
+ ? readonly ApiItemLike[]
+ : ApiItem[K] | undefined;
};
interface ResolvedCanonicalReference {
@@ -100,12 +104,12 @@ 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 })),
+ .map((member) => ({ kind: member.kind, displayName: member.memberIdentifier!.identifier! })),
},
};
}
@@ -114,11 +118,11 @@ export function resolveCanonicalReference(
}
export function mapMeaningToKind(meaning: Meaning): ApiItemKind {
- return [...kindToMeaning.entries()].find((mapping) => mapping[1] === meaning)?.[0];
+ return [...kindToMeaning.entries()].find((mapping) => mapping[1] === meaning)?.[0] ?? ApiItemKind.None;
}
export function mapKindToMeaning(kind: ApiItemKind): Meaning {
- return kindToMeaning.get(kind);
+ return kindToMeaning.get(kind) ?? Meaning.Variable;
}
export function memberPredicate(
From 7d1ec92cd1bb6964585ddd9b1e8458481ca320ea Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Mon, 20 Nov 2023 17:10:25 +0100
Subject: [PATCH 6/8] refactor: simplify ApiItemLike interface
---
.../src/components/documentation/util.ts | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/apps/website/src/components/documentation/util.ts b/apps/website/src/components/documentation/util.ts
index 9c2f233db568..6ef4df07ccd6 100644
--- a/apps/website/src/components/documentation/util.ts
+++ b/apps/website/src/components/documentation/util.ts
@@ -18,17 +18,13 @@ 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'
- ? ApiItem[K]
- : K extends 'kind'
- ? string
- : K extends 'parent'
- ? ApiItemLike | undefined
- : K extends 'members'
- ? readonly ApiItemLike[]
- : ApiItem[K] | undefined;
-};
+export interface ApiItemLike {
+ containerKey?: string;
+ displayName: string;
+ kind: string;
+ members?: readonly ApiItemLike[];
+ parent?: ApiItemLike | undefined;
+}
interface ResolvedCanonicalReference {
item: ApiItemLike;
From d800dbb8294a5a3aa53c52d1be2a36ed7babe191 Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Tue, 21 Nov 2023 15:39:41 +0100
Subject: [PATCH 7/8] refactor: apply suggestions
---
apps/website/src/components/ExcerptText.tsx | 10 +++++++---
.../src/components/documentation/tsdoc/TSDoc.tsx | 10 +++++++---
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/apps/website/src/components/ExcerptText.tsx b/apps/website/src/components/ExcerptText.tsx
index bcf5525632e5..c5050ef2fbcd 100644
--- a/apps/website/src/components/ExcerptText.tsx
+++ b/apps/website/src/components/ExcerptText.tsx
@@ -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 (
diff --git a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
index 4253f2129c4d..487e2edb0c8e 100644
--- a/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
+++ b/apps/website/src/components/documentation/tsdoc/TSDoc.tsx
@@ -62,9 +62,13 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
// 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}`;
+ if (kind === 'enum' && members?.[0]) {
+ href += `/enum/${displayName}#${members[0].displayName}`;
+ } else if (kind === 'type' || kind === 'var') {
+ href += `#${displayName}`;
+ } else {
+ href += `/${kind}/${displayName}`;
+ }
return (
From f6d86bf11ff1c4d51d43b4ed88056c3dac2fae82 Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Wed, 22 Nov 2023 07:55:50 +0100
Subject: [PATCH 8/8] fix: missing newline in docComment
---
.../src/generators/ApiModelGenerator.ts | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/packages/api-extractor/src/generators/ApiModelGenerator.ts b/packages/api-extractor/src/generators/ApiModelGenerator.ts
index 701b54ccd671..567d232c9adb 100644
--- a/packages/api-extractor/src/generators/ApiModelGenerator.ts
+++ b/packages/api-extractor/src/generators/ApiModelGenerator.ts
@@ -1053,7 +1053,7 @@ export class ApiModelGenerator {
.join('') ?? ''
}${
jsDoc.returns?.length && !Array.isArray(jsDoc.returns[0])
- ? ` * @returns ${this._fixLinkTags(jsDoc.returns[0]!.description) ?? ''}`
+ ? ` * @returns ${this._fixLinkTags(jsDoc.returns[0]!.description) ?? ''}\n`
: ''
}${
jsDoc.examples?.map((example) => ` * @example\n * \`\`\`js\n * ${example}\n * \`\`\`\n`).join('') ?? ''
@@ -1143,7 +1143,7 @@ export class ApiModelGenerator {
.join('') ?? ''
}${
jsDoc.returns?.length && !Array.isArray(jsDoc.returns[0])
- ? ` * @returns ${this._fixLinkTags(jsDoc.returns[0]!.description) ?? ''}`
+ ? ` * @returns ${this._fixLinkTags(jsDoc.returns[0]!.description) ?? ''}\n`
: ''
}${
jsDoc.deprecated
@@ -1409,9 +1409,9 @@ export class ApiModelGenerator {
: ''
}${
'returns' in jsDoc
- ? jsDoc.returns.map(
- (ret) => ` * @returns ${Array.isArray(ret) ? '' : this._fixLinkTags(ret.description) ?? ''}\n`,
- )
+ ? jsDoc.returns
+ .map((ret) => ` * @returns ${Array.isArray(ret) ? '' : this._fixLinkTags(ret.description) ?? ''}\n`)
+ .join('')
: ''
} */`,
).docComment
@@ -1854,7 +1854,7 @@ export class ApiModelGenerator {
.join('') ?? ''
}${
method.returns?.length && !Array.isArray(method.returns[0])
- ? ` * @returns ${this._fixLinkTags(method.returns[0]!.description) ?? ''}`
+ ? ` * @returns ${this._fixLinkTags(method.returns[0]!.description) ?? ''}\n`
: ''
}${method.examples?.map((example) => ` * @example\n * \`\`\`js\n * ${example}\n * \`\`\`\n`).join('') ?? ''}${
method.deprecated