fix(website): misc improvements (#9940)

* refactor: use tokenRange for typeParams in heritage

* fix: correct type param replacement

* fix: ae config, link builtin in summary, `: | T` => `: T`, mainlib tsdoc

* fix: requested changes and tests

* chore: better deprecation messages and code cleanup

* fix: cleanup optional chainings

---------

Co-authored-by: Almeida <almeidx@pm.me>
This commit is contained in:
Qjuh 2023-11-13 09:55:23 +01:00 committed by GitHub
parent 2d63d93558
commit b79351ba99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 134 additions and 97 deletions

View file

@ -89,48 +89,50 @@
* DEFAULT VALUE: no overrideTsconfig section * DEFAULT VALUE: no overrideTsconfig section
*/ */
"overrideTsconfig": { "overrideTsconfig": {
// Type Checking "compilerOptions": {
"allowUnreachableCode": false, // Type Checking
"allowUnusedLabels": false, "allowUnreachableCode": false,
"exactOptionalPropertyTypes": true, "allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true, "exactOptionalPropertyTypes": true,
"noImplicitOverride": true, "noFallthroughCasesInSwitch": true,
"noImplicitReturns": true, "noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": false, "noImplicitReturns": true,
"noUncheckedIndexedAccess": true, "noPropertyAccessFromIndexSignature": false,
"noUnusedLocals": true, "noUncheckedIndexedAccess": true,
"noUnusedParameters": true, "noUnusedLocals": true,
"strict": true, "noUnusedParameters": true,
"strict": true,
// Modules // Modules
"allowArbitraryExtensions": false, "allowArbitraryExtensions": false,
"allowImportingTsExtensions": false, "allowImportingTsExtensions": false,
"module": "ESNext", "module": "ESNext",
"moduleResolution": "node", "moduleResolution": "nodenext",
"resolveJsonModule": true, "resolveJsonModule": true,
"resolvePackageJsonExports": false, "resolvePackageJsonExports": false,
"resolvePackageJsonImports": false, "resolvePackageJsonImports": false,
// Emit // Emit
"declaration": true, "declaration": true,
"declarationMap": true, "declarationMap": true,
"importHelpers": false, "importHelpers": false,
"newLine": "lf", "newLine": "lf",
"noEmitHelpers": true, "noEmitHelpers": true,
"outDir": "dist", "outDir": "dist",
"removeComments": false, "removeComments": false,
"sourceMap": true, "sourceMap": true,
// Interop Constraints // Interop Constraints
"esModuleInterop": false, "esModuleInterop": false,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"isolatedModules": true, "isolatedModules": true,
// Language and Environment // Language and Environment
"experimentalDecorators": true, "experimentalDecorators": true,
"lib": ["ESNext"], "lib": ["ESNext"],
"target": "ES2022", "target": "ES2022",
"useDefineForClassFields": true "useDefineForClassFields": true
}
} }
/** /**
* This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended * This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended

View file

@ -4,6 +4,8 @@ import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
import type { Route } from 'next'; import type { Route } from 'next';
import Link from 'next/link'; import Link from 'next/link';
import { Fragment, useCallback, type ReactNode } from 'react'; import { Fragment, useCallback, type ReactNode } from 'react';
import { DocumentationLink } from '~/components/DocumentationLink';
import { BuiltinDocumentationLinks } from '~/util/builtinDocumentationLinks';
import { ItemLink } from '../../ItemLink'; import { ItemLink } from '../../ItemLink';
import { SyntaxHighlighter } from '../../SyntaxHighlighter'; import { SyntaxHighlighter } from '../../SyntaxHighlighter';
import { resolveItemURI } from '../util'; import { resolveItemURI } from '../util';
@ -32,10 +34,24 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
const { codeDestination, urlDestination, linkText } = tsdoc as DocLinkTag; const { codeDestination, urlDestination, linkText } = tsdoc as DocLinkTag;
if (codeDestination) { if (codeDestination) {
// TODO: Real fix in api-extractor needed if (
const currentItem = item.getAssociatedPackage(); !codeDestination.importPath &&
const foundItem = item.getAssociatedModel()?.resolveDeclarationReference(codeDestination, currentItem) !codeDestination.packageName &&
.resolvedApiItem; codeDestination.memberReferences.length === 1 &&
codeDestination.memberReferences[0]!.memberIdentifier &&
codeDestination.memberReferences[0]!.memberIdentifier.identifier in BuiltinDocumentationLinks
) {
const typeName = codeDestination.memberReferences[0]!.memberIdentifier.identifier;
const href = BuiltinDocumentationLinks[typeName as keyof typeof BuiltinDocumentationLinks];
return (
<DocumentationLink key={`${typeName}-${idx}`} href={href}>
{typeName}
</DocumentationLink>
);
}
const declarationReference = item.getAssociatedModel()?.resolveDeclarationReference(codeDestination, item);
const foundItem = declarationReference?.resolvedApiItem;
if (!foundItem) return null; if (!foundItem) return null;
@ -44,6 +60,7 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
className="rounded font-mono text-blurple outline-none focus:ring focus:ring-width-2 focus:ring-blurple" className="rounded font-mono text-blurple outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
itemURI={resolveItemURI(foundItem)} itemURI={resolveItemURI(foundItem)}
key={idx} key={idx}
packageName={item.getAssociatedPackage()?.displayName.replace('@discordjs/', '')}
> >
{linkText ?? foundItem.displayName} {linkText ?? foundItem.displayName}
</ItemLink> </ItemLink>

View file

@ -5,12 +5,12 @@
"apiReport": { "apiReport": {
"enabled": true, "enabled": true,
"reportFolder": "../../../common/reviews/api" "reportFolder": "<projectFolder>/docs/review"
}, },
"docModel": { "docModel": {
"enabled": true, "enabled": true,
"apiJsonFilePath": "../../../common/temp/api/<unscopedPackageName>.api.json" "apiJsonFilePath": "<projectFolder>/docs/<unscopedPackageName>.api.json"
}, },
"dtsRollup": { "dtsRollup": {

View file

@ -4,7 +4,7 @@
import { ReleaseTag } from '@discordjs/api-extractor-model'; import { ReleaseTag } from '@discordjs/api-extractor-model';
import * as tsdoc from '@microsoft/tsdoc'; import * as tsdoc from '@microsoft/tsdoc';
import { PackageJsonLookup, Sort, InternalError } from '@rushstack/node-core-library'; import { PackageJsonLookup, Sort, InternalError } from '@rushstack/node-core-library';
import * as ts from 'typescript'; import ts from 'typescript';
import { PackageDocComment } from '../aedoc/PackageDocComment.js'; import { PackageDocComment } from '../aedoc/PackageDocComment.js';
import type { AstDeclaration } from '../analyzer/AstDeclaration.js'; import type { AstDeclaration } from '../analyzer/AstDeclaration.js';
import type { AstEntity } from '../analyzer/AstEntity.js'; import type { AstEntity } from '../analyzer/AstEntity.js';

View file

@ -36,7 +36,6 @@ import {
Navigation, Navigation,
} from '@discordjs/api-extractor-model'; } from '@discordjs/api-extractor-model';
import type * as tsdoc from '@microsoft/tsdoc'; import type * as tsdoc from '@microsoft/tsdoc';
import { TSDocParser } from '@microsoft/tsdoc';
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js'; import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
import { JsonFile, Path } from '@rushstack/node-core-library'; import { JsonFile, Path } from '@rushstack/node-core-library';
import * as ts from 'typescript'; import * as ts from 'typescript';
@ -220,12 +219,16 @@ export class ApiModelGenerator {
private readonly _apiModel: ApiModel; private readonly _apiModel: ApiModel;
private readonly _tsDocParser: tsdoc.TSDocParser;
private readonly _referenceGenerator: DeclarationReferenceGenerator; private readonly _referenceGenerator: DeclarationReferenceGenerator;
public constructor(collector: Collector) { public constructor(collector: Collector) {
this._collector = collector; this._collector = collector;
this._apiModel = new ApiModel(); this._apiModel = new ApiModel();
this._referenceGenerator = new DeclarationReferenceGenerator(collector); this._referenceGenerator = new DeclarationReferenceGenerator(collector);
// @ts-expect-error we reuse the private tsdocParser from collector here
this._tsDocParser = collector._tsdocParser;
} }
public get apiModel(): ApiModel { public get apiModel(): ApiModel {
@ -500,7 +503,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = parent?.construct const docComment: tsdoc.DocComment | undefined = parent?.construct
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/*+\n * ${fixLinkTags(parent.construct.description)}\n${ `/*+\n * ${fixLinkTags(parent.construct.description)}\n${
parent.construct.params parent.construct.params
?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`) ?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`)
@ -586,7 +589,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description)}\n${jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${ `/**\n * ${fixLinkTags(jsDoc.description)}\n${jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${
jsDoc.deprecated jsDoc.deprecated
? ` * @deprecated ${ ? ` * @deprecated ${
@ -658,7 +661,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = parent?.construct const docComment: tsdoc.DocComment | undefined = parent?.construct
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/*+\n * ${fixLinkTags(parent.construct.description)}\n${ `/*+\n * ${fixLinkTags(parent.construct.description)}\n${
parent.construct.params parent.construct.params
?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`) ?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`)
@ -789,7 +792,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description)}\n${ `/**\n * ${fixLinkTags(jsDoc.description)}\n${
jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ?? jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ??
'' ''
@ -916,7 +919,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description)}\n${jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${ `/**\n * ${fixLinkTags(jsDoc.description)}\n${jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${
jsDoc.deprecated jsDoc.deprecated
? ` * @deprecated ${ ? ` * @deprecated ${
@ -980,7 +983,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description)}\n${ `/**\n * ${fixLinkTags(jsDoc.description)}\n${
jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ?? jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ??
'' ''
@ -1058,7 +1061,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description)}\n${ `/**\n * ${fixLinkTags(jsDoc.description)}\n${
jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ?? jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ??
'' ''
@ -1166,7 +1169,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description)}\n${ `/**\n * ${fixLinkTags(jsDoc.description)}\n${
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : '' 'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${ }${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
@ -1229,7 +1232,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description)}\n${ `/**\n * ${fixLinkTags(jsDoc.description)}\n${
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : '' 'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${ }${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
@ -1290,7 +1293,7 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? new TSDocParser().parseString( ? this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description) ?? ''}\n${ `/**\n * ${fixLinkTags(jsDoc.description) ?? ''}\n${
'params' in jsDoc 'params' in jsDoc
? jsDoc.params.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ? jsDoc.params.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('')
@ -1425,7 +1428,7 @@ export class ApiModelGenerator {
}); });
} }
const docComment: tsdoc.DocComment | undefined = new TSDocParser().parseString( const docComment: tsdoc.DocComment | undefined = this._tsDocParser.parseString(
`/**\n * ${fixLinkTags(jsDoc.description)}\n${ `/**\n * ${fixLinkTags(jsDoc.description)}\n${
jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ?? '' jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ?? ''
}${'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''}${ }${'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''}${

View file

@ -135,7 +135,7 @@ export class ExcerptBuilder {
return { startIndex: 0, endIndex: 0, typeParameters: [] }; return { startIndex: 0, endIndex: 0, typeParameters: [] };
} }
public static isPrimitiveKeyword(node: ts.Node): boolean { private static _isPrimitiveKeyword(node: ts.Node): boolean {
switch (node.kind) { switch (node.kind) {
case ts.SyntaxKind.AnyKeyword: case ts.SyntaxKind.AnyKeyword:
case ts.SyntaxKind.BigIntKeyword: case ts.SyntaxKind.BigIntKeyword:
@ -156,6 +156,15 @@ export class ExcerptBuilder {
} }
} }
private static _isRedundantBarAfterColon(span: Span) {
return (
span.kind === ts.SyntaxKind.BarToken &&
span.previousSibling === undefined &&
(span.parent?.parent?.previousSibling?.kind === ts.SyntaxKind.LessThanToken ||
span.parent?.parent?.previousSibling?.kind === ts.SyntaxKind.ColonToken)
);
}
private static _buildSpan(excerptTokens: IExcerptToken[], span: Span, state: IBuildSpanState): boolean { private static _buildSpan(excerptTokens: IExcerptToken[], span: Span, state: IBuildSpanState): boolean {
if (span.kind === ts.SyntaxKind.JSDocComment) { if (span.kind === ts.SyntaxKind.JSDocComment) {
// Discard any comments // Discard any comments
@ -174,21 +183,21 @@ export class ExcerptBuilder {
if (span.prefix) { if (span.prefix) {
let canonicalReference: DeclarationReference | undefined; let canonicalReference: DeclarationReference | undefined;
if (span.kind === ts.SyntaxKind.Identifier) { if (ts.isIdentifier(span.node)) {
const name: ts.Identifier = span.node as ts.Identifier; const name: ts.Identifier = span.node;
canonicalReference = state.referenceGenerator.getDeclarationReferenceForIdentifier(name); canonicalReference = state.referenceGenerator.getDeclarationReferenceForIdentifier(name);
} }
if (canonicalReference) { if (canonicalReference) {
ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Reference, span.prefix, canonicalReference); ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Reference, span.prefix, canonicalReference);
} else if ( } else if (
ExcerptBuilder.isPrimitiveKeyword(span.node) || ExcerptBuilder._isPrimitiveKeyword(span.node) ||
(span.node.kind === ts.SyntaxKind.Identifier && (ts.isIdentifier(span.node) &&
((ts.isTypeReferenceNode(span.node.parent) && span.node.parent.typeName === span.node) || ((ts.isTypeReferenceNode(span.node.parent) && span.node.parent.typeName === span.node) ||
(ts.isTypeParameterDeclaration(span.node.parent) && span.node.parent.name === span.node))) (ts.isTypeParameterDeclaration(span.node.parent) && span.node.parent.name === span.node)))
) { ) {
ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Reference, span.prefix); ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Reference, span.prefix);
} else { } else if (!ExcerptBuilder._isRedundantBarAfterColon(span)) {
ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Content, span.prefix); ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Content, span.prefix);
} }
@ -313,6 +322,12 @@ export class ExcerptBuilder {
!startOrEndIndices.has(currentIndex) !startOrEndIndices.has(currentIndex)
) { ) {
prevToken.text += currentToken.text; prevToken.text += currentToken.text;
// Remove BarTokens from excerpts if they immediately follow a LessThanToken, e.g. `Promise< | Something>`
// would become `Promise<Something>`
if (/<\s*\|/.test(prevToken.text)) {
prevToken.text = prevToken.text.replace(/<\s*\|\s*/, '<');
}
mergeCount = 1; mergeCount = 1;
} else { } else {
// Otherwise, no merging can occur here. Continue to the next index. // Otherwise, no merging can occur here. Continue to the next index.

View file

@ -991,7 +991,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
public fetchVoiceRegions(): Promise<Collection<string, VoiceRegion>>; public fetchVoiceRegions(): Promise<Collection<string, VoiceRegion>>;
public fetchSticker(id: Snowflake): Promise<Sticker>; public fetchSticker(id: Snowflake): Promise<Sticker>;
public fetchStickerPacks(): Promise<Collection<Snowflake, StickerPack>>; public fetchStickerPacks(): Promise<Collection<Snowflake, StickerPack>>;
/** @deprecated Use {@link fetchStickerPacks} instead. */ /** @deprecated Use {@link Client#fetchStickerPacks} instead. */
public fetchPremiumStickerPacks(): ReturnType<Client['fetchStickerPacks']>; public fetchPremiumStickerPacks(): ReturnType<Client['fetchStickerPacks']>;
public fetchWebhook(id: Snowflake, token?: string): Promise<Webhook>; public fetchWebhook(id: Snowflake, token?: string): Promise<Webhook>;
public fetchGuildWidget(guild: GuildResolvable): Promise<Widget>; public fetchGuildWidget(guild: GuildResolvable): Promise<Widget>;
@ -1870,7 +1870,7 @@ export class BaseInteraction<Cached extends CacheType = CacheType> extends Base
public isMessageContextMenuCommand(): this is MessageContextMenuCommandInteraction<Cached>; public isMessageContextMenuCommand(): this is MessageContextMenuCommandInteraction<Cached>;
public isModalSubmit(): this is ModalSubmitInteraction<Cached>; public isModalSubmit(): this is ModalSubmitInteraction<Cached>;
public isUserContextMenuCommand(): this is UserContextMenuCommandInteraction<Cached>; public isUserContextMenuCommand(): this is UserContextMenuCommandInteraction<Cached>;
/** @deprecated Use {@link isStringSelectMenu} instead. */ /** @deprecated Use {@link BaseInteraction#isStringSelectMenu} instead. */
public isSelectMenu(): this is StringSelectMenuInteraction<Cached>; public isSelectMenu(): this is StringSelectMenuInteraction<Cached>;
public isAnySelectMenu(): this is AnySelectMenuInteraction<Cached>; public isAnySelectMenu(): this is AnySelectMenuInteraction<Cached>;
public isStringSelectMenu(): this is StringSelectMenuInteraction<Cached>; public isStringSelectMenu(): this is StringSelectMenuInteraction<Cached>;
@ -1957,12 +1957,12 @@ export class Invite extends Base {
public toJSON(): unknown; public toJSON(): unknown;
public toString(): string; public toString(): string;
public static InvitesPattern: RegExp; public static InvitesPattern: RegExp;
/** @deprecated */ /** @deprecated Public Stage Instances don't exist anymore */
public stageInstance: InviteStageInstance | null; public stageInstance: InviteStageInstance | null;
public guildScheduledEvent: GuildScheduledEvent | null; public guildScheduledEvent: GuildScheduledEvent | null;
} }
/** @deprecated */ /** @deprecated Public Stage Instances don't exist anymore */
export class InviteStageInstance extends Base { export class InviteStageInstance extends Base {
private constructor(client: Client<true>, data: RawInviteStageInstance, channelId: Snowflake, guildId: Snowflake); private constructor(client: Client<true>, data: RawInviteStageInstance, channelId: Snowflake, guildId: Snowflake);
public channelId: Snowflake; public channelId: Snowflake;
@ -3065,7 +3065,7 @@ export class TeamMember extends Base {
private constructor(team: Team, data: RawTeamMemberData); private constructor(team: Team, data: RawTeamMemberData);
public team: Team; public team: Team;
public get id(): Snowflake; public get id(): Snowflake;
/** @deprecated Use {@link role} instead. */ /** @deprecated Use {@link TeamMember#role} instead. */
public permissions: string[]; public permissions: string[];
public membershipState: TeamMemberMembershipState; public membershipState: TeamMemberMembershipState;
public user: User; public user: User;
@ -3632,24 +3632,24 @@ export enum DiscordjsErrorCodes {
TokenMissing = 'TokenMissing', TokenMissing = 'TokenMissing',
ApplicationCommandPermissionsTokenMissing = 'ApplicationCommandPermissionsTokenMissing', ApplicationCommandPermissionsTokenMissing = 'ApplicationCommandPermissionsTokenMissing',
/** @deprecated */ /** @deprecated WebSocket errors are now handled in `@discordjs/ws` */
WSCloseRequested = 'WSCloseRequested', WSCloseRequested = 'WSCloseRequested',
/** @deprecated */ /** @deprecated WebSocket errors are now handled in `@discordjs/ws` */
WSConnectionExists = 'WSConnectionExists', WSConnectionExists = 'WSConnectionExists',
/** @deprecated */ /** @deprecated WebSocket errors are now handled in `@discordjs/ws` */
WSNotOpen = 'WSNotOpen', WSNotOpen = 'WSNotOpen',
/** @deprecated */ /** @deprecated No longer in use */
ManagerDestroyed = 'ManagerDestroyed', ManagerDestroyed = 'ManagerDestroyed',
BitFieldInvalid = 'BitFieldInvalid', BitFieldInvalid = 'BitFieldInvalid',
/** @deprecated */ /** @deprecated This error is now handled in `@discordjs/ws` */
ShardingInvalid = 'ShardingInvalid', ShardingInvalid = 'ShardingInvalid',
/** @deprecated */ /** @deprecated This error is now handled in `@discordjs/ws` */
ShardingRequired = 'ShardingRequired', ShardingRequired = 'ShardingRequired',
/** @deprecated */ /** @deprecated This error is now handled in `@discordjs/ws` */
InvalidIntents = 'InvalidIntents', InvalidIntents = 'InvalidIntents',
/** @deprecated */ /** @deprecated This error is now handled in `@discordjs/ws` */
DisallowedIntents = 'DisallowedIntents', DisallowedIntents = 'DisallowedIntents',
ShardingNoShards = 'ShardingNoShards', ShardingNoShards = 'ShardingNoShards',
ShardingInProcess = 'ShardingInProcess', ShardingInProcess = 'ShardingInProcess',
@ -3669,29 +3669,29 @@ export enum DiscordjsErrorCodes {
InviteOptionsMissingChannel = 'InviteOptionsMissingChannel', InviteOptionsMissingChannel = 'InviteOptionsMissingChannel',
/** @deprecated */ /** @deprecated Button validation errors are now handled in `@discordjs/builders` */
ButtonLabel = 'ButtonLabel', ButtonLabel = 'ButtonLabel',
/** @deprecated */ /** @deprecated Button validation errors are now handled in `@discordjs/builders` */
ButtonURL = 'ButtonURL', ButtonURL = 'ButtonURL',
/** @deprecated */ /** @deprecated Button validation errors are now handled in `@discordjs/builders` */
ButtonCustomId = 'ButtonCustomId', ButtonCustomId = 'ButtonCustomId',
/** @deprecated */ /** @deprecated Select Menu validation errors are now handled in `@discordjs/builders` */
SelectMenuCustomId = 'SelectMenuCustomId', SelectMenuCustomId = 'SelectMenuCustomId',
/** @deprecated */ /** @deprecated Select Menu validation errors are now handled in `@discordjs/builders` */
SelectMenuPlaceholder = 'SelectMenuPlaceholder', SelectMenuPlaceholder = 'SelectMenuPlaceholder',
/** @deprecated */ /** @deprecated Select Menu validation errors are now handled in `@discordjs/builders` */
SelectOptionLabel = 'SelectOptionLabel', SelectOptionLabel = 'SelectOptionLabel',
/** @deprecated */ /** @deprecated Select Menu validation errors are now handled in `@discordjs/builders` */
SelectOptionValue = 'SelectOptionValue', SelectOptionValue = 'SelectOptionValue',
/** @deprecated */ /** @deprecated Select Menu validation errors are now handled in `@discordjs/builders` */
SelectOptionDescription = 'SelectOptionDescription', SelectOptionDescription = 'SelectOptionDescription',
InteractionCollectorError = 'InteractionCollectorError', InteractionCollectorError = 'InteractionCollectorError',
FileNotFound = 'FileNotFound', FileNotFound = 'FileNotFound',
/** @deprecated */ /** @deprecated No longer in use */
UserBannerNotFetched = 'UserBannerNotFetched', UserBannerNotFetched = 'UserBannerNotFetched',
UserNoDMChannel = 'UserNoDMChannel', UserNoDMChannel = 'UserNoDMChannel',
@ -3702,16 +3702,16 @@ export enum DiscordjsErrorCodes {
ReqResourceType = 'ReqResourceType', ReqResourceType = 'ReqResourceType',
/** @deprecated */ /** @deprecated This error is now handled in `@discordjs/rest` */
ImageFormat = 'ImageFormat', ImageFormat = 'ImageFormat',
/** @deprecated */ /** @deprecated This error is now handled in `@discordjs/rest` */
ImageSize = 'ImageSize', ImageSize = 'ImageSize',
MessageBulkDeleteType = 'MessageBulkDeleteType', MessageBulkDeleteType = 'MessageBulkDeleteType',
MessageNonceType = 'MessageNonceType', MessageNonceType = 'MessageNonceType',
MessageContentType = 'MessageContentType', MessageContentType = 'MessageContentType',
/** @deprecated */ /** @deprecated No longer in use */
SplitMaxLen = 'SplitMaxLen', SplitMaxLen = 'SplitMaxLen',
BanResolveId = 'BanResolveId', BanResolveId = 'BanResolveId',
@ -3747,14 +3747,14 @@ export enum DiscordjsErrorCodes {
EmojiType = 'EmojiType', EmojiType = 'EmojiType',
EmojiManaged = 'EmojiManaged', EmojiManaged = 'EmojiManaged',
MissingManageGuildExpressionsPermission = 'MissingManageGuildExpressionsPermission', MissingManageGuildExpressionsPermission = 'MissingManageGuildExpressionsPermission',
/** @deprecated Use {@link MissingManageGuildExpressionsPermission} instead. */ /** @deprecated Use {@link DiscordjsErrorCodes.MissingManageGuildExpressionsPermission} instead. */
MissingManageEmojisAndStickersPermission = 'MissingManageEmojisAndStickersPermission', MissingManageEmojisAndStickersPermission = 'MissingManageEmojisAndStickersPermission',
NotGuildSticker = 'NotGuildSticker', NotGuildSticker = 'NotGuildSticker',
ReactionResolveUser = 'ReactionResolveUser', ReactionResolveUser = 'ReactionResolveUser',
/** @deprecated */ /** @deprecated Not used anymore since the introduction of `GUILD_WEB_PAGE_VANITY_URL` feature */
VanityURL = 'VanityURL', VanityURL = 'VanityURL',
InviteResolveCode = 'InviteResolveCode', InviteResolveCode = 'InviteResolveCode',
@ -3771,7 +3771,7 @@ export enum DiscordjsErrorCodes {
InteractionAlreadyReplied = 'InteractionAlreadyReplied', InteractionAlreadyReplied = 'InteractionAlreadyReplied',
InteractionNotReplied = 'InteractionNotReplied', InteractionNotReplied = 'InteractionNotReplied',
/** @deprecated */ /** @deprecated Not used anymore since ephemeral replies can now be deleted */
InteractionEphemeralReplied = 'InteractionEphemeralReplied', InteractionEphemeralReplied = 'InteractionEphemeralReplied',
CommandInteractionOptionNotFound = 'CommandInteractionOptionNotFound', CommandInteractionOptionNotFound = 'CommandInteractionOptionNotFound',
@ -4801,7 +4801,7 @@ export interface AwaitReactionsOptions extends ReactionCollectorOptions {
} }
export interface BanOptions { export interface BanOptions {
/** @deprecated Use {@link deleteMessageSeconds} instead. */ /** @deprecated Use {@link BanOptions#deleteMessageSeconds} instead. */
deleteMessageDays?: number; deleteMessageDays?: number;
deleteMessageSeconds?: number; deleteMessageSeconds?: number;
reason?: string; reason?: string;
@ -5001,7 +5001,7 @@ export interface ClientEvents {
typingStart: [typing: Typing]; typingStart: [typing: Typing];
userUpdate: [oldUser: User | PartialUser, newUser: User]; userUpdate: [oldUser: User | PartialUser, newUser: User];
voiceStateUpdate: [oldState: VoiceState, newState: VoiceState]; voiceStateUpdate: [oldState: VoiceState, newState: VoiceState];
/** @deprecated Use {@link webhooksUpdate} instead. */ /** @deprecated Use {@link ClientEvents#webhooksUpdate} instead. */
webhookUpdate: ClientEvents['webhooksUpdate']; webhookUpdate: ClientEvents['webhooksUpdate'];
webhooksUpdate: [channel: TextChannel | NewsChannel | VoiceChannel | ForumChannel | MediaChannel]; webhooksUpdate: [channel: TextChannel | NewsChannel | VoiceChannel | ForumChannel | MediaChannel];
interactionCreate: [interaction: Interaction]; interactionCreate: [interaction: Interaction];
@ -5061,10 +5061,10 @@ export interface ClientUserEditOptions {
} }
export interface CloseEvent { export interface CloseEvent {
/** @deprecated */ /** @deprecated Not used anymore since using {@link @discordjs/ws#WebSocketManager} internally */
wasClean: boolean; wasClean: boolean;
code: number; code: number;
/** @deprecated */ /** @deprecated Not used anymore since using {@link @discordjs/ws#WebSocketManager} internally */
reason: string; reason: string;
} }
@ -5390,11 +5390,11 @@ export interface FetchGuildScheduledEventSubscribersOptions {
withMember?: boolean; withMember?: boolean;
} }
interface FetchInviteOptions extends BaseFetchOptions { export interface FetchInviteOptions extends BaseFetchOptions {
code: string; code: string;
} }
interface FetchInvitesOptions { export interface FetchInvitesOptions {
channelId?: GuildInvitableChannelResolvable; channelId?: GuildInvitableChannelResolvable;
cache?: boolean; cache?: boolean;
} }