Skip to content

Commit b79351b

Browse files
Qjuhalmeidx
andauthored
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 <[email protected]>
1 parent 2d63d93 commit b79351b

File tree

7 files changed

+134
-97
lines changed

7 files changed

+134
-97
lines changed

api-extractor.json

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -89,48 +89,50 @@
8989
* DEFAULT VALUE: no overrideTsconfig section
9090
*/
9191
"overrideTsconfig": {
92-
// Type Checking
93-
"allowUnreachableCode": false,
94-
"allowUnusedLabels": false,
95-
"exactOptionalPropertyTypes": true,
96-
"noFallthroughCasesInSwitch": true,
97-
"noImplicitOverride": true,
98-
"noImplicitReturns": true,
99-
"noPropertyAccessFromIndexSignature": false,
100-
"noUncheckedIndexedAccess": true,
101-
"noUnusedLocals": true,
102-
"noUnusedParameters": true,
103-
"strict": true,
92+
"compilerOptions": {
93+
// Type Checking
94+
"allowUnreachableCode": false,
95+
"allowUnusedLabels": false,
96+
"exactOptionalPropertyTypes": true,
97+
"noFallthroughCasesInSwitch": true,
98+
"noImplicitOverride": true,
99+
"noImplicitReturns": true,
100+
"noPropertyAccessFromIndexSignature": false,
101+
"noUncheckedIndexedAccess": true,
102+
"noUnusedLocals": true,
103+
"noUnusedParameters": true,
104+
"strict": true,
104105

105-
// Modules
106-
"allowArbitraryExtensions": false,
107-
"allowImportingTsExtensions": false,
108-
"module": "ESNext",
109-
"moduleResolution": "node",
110-
"resolveJsonModule": true,
111-
"resolvePackageJsonExports": false,
112-
"resolvePackageJsonImports": false,
106+
// Modules
107+
"allowArbitraryExtensions": false,
108+
"allowImportingTsExtensions": false,
109+
"module": "ESNext",
110+
"moduleResolution": "nodenext",
111+
"resolveJsonModule": true,
112+
"resolvePackageJsonExports": false,
113+
"resolvePackageJsonImports": false,
113114

114-
// Emit
115-
"declaration": true,
116-
"declarationMap": true,
117-
"importHelpers": false,
118-
"newLine": "lf",
119-
"noEmitHelpers": true,
120-
"outDir": "dist",
121-
"removeComments": false,
122-
"sourceMap": true,
115+
// Emit
116+
"declaration": true,
117+
"declarationMap": true,
118+
"importHelpers": false,
119+
"newLine": "lf",
120+
"noEmitHelpers": true,
121+
"outDir": "dist",
122+
"removeComments": false,
123+
"sourceMap": true,
123124

124-
// Interop Constraints
125-
"esModuleInterop": false,
126-
"forceConsistentCasingInFileNames": true,
127-
"isolatedModules": true,
125+
// Interop Constraints
126+
"esModuleInterop": false,
127+
"forceConsistentCasingInFileNames": true,
128+
"isolatedModules": true,
128129

129-
// Language and Environment
130-
"experimentalDecorators": true,
131-
"lib": ["ESNext"],
132-
"target": "ES2022",
133-
"useDefineForClassFields": true
130+
// Language and Environment
131+
"experimentalDecorators": true,
132+
"lib": ["ESNext"],
133+
"target": "ES2022",
134+
"useDefineForClassFields": true
135+
}
134136
}
135137
/**
136138
* This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended

apps/website/src/components/documentation/tsdoc/TSDoc.tsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
44
import type { Route } from 'next';
55
import Link from 'next/link';
66
import { Fragment, useCallback, type ReactNode } from 'react';
7+
import { DocumentationLink } from '~/components/DocumentationLink';
8+
import { BuiltinDocumentationLinks } from '~/util/builtinDocumentationLinks';
79
import { ItemLink } from '../../ItemLink';
810
import { SyntaxHighlighter } from '../../SyntaxHighlighter';
911
import { resolveItemURI } from '../util';
@@ -32,10 +34,24 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
3234
const { codeDestination, urlDestination, linkText } = tsdoc as DocLinkTag;
3335

3436
if (codeDestination) {
35-
// TODO: Real fix in api-extractor needed
36-
const currentItem = item.getAssociatedPackage();
37-
const foundItem = item.getAssociatedModel()?.resolveDeclarationReference(codeDestination, currentItem)
38-
.resolvedApiItem;
37+
if (
38+
!codeDestination.importPath &&
39+
!codeDestination.packageName &&
40+
codeDestination.memberReferences.length === 1 &&
41+
codeDestination.memberReferences[0]!.memberIdentifier &&
42+
codeDestination.memberReferences[0]!.memberIdentifier.identifier in BuiltinDocumentationLinks
43+
) {
44+
const typeName = codeDestination.memberReferences[0]!.memberIdentifier.identifier;
45+
const href = BuiltinDocumentationLinks[typeName as keyof typeof BuiltinDocumentationLinks];
46+
return (
47+
<DocumentationLink key={`${typeName}-${idx}`} href={href}>
48+
{typeName}
49+
</DocumentationLink>
50+
);
51+
}
52+
53+
const declarationReference = item.getAssociatedModel()?.resolveDeclarationReference(codeDestination, item);
54+
const foundItem = declarationReference?.resolvedApiItem;
3955

4056
if (!foundItem) return null;
4157

@@ -44,6 +60,7 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
4460
className="rounded font-mono text-blurple outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
4561
itemURI={resolveItemURI(foundItem)}
4662
key={idx}
63+
packageName={item.getAssociatedPackage()?.displayName.replace('@discordjs/', '')}
4764
>
4865
{linkText ?? foundItem.displayName}
4966
</ItemLink>

packages/api-extractor/config/api-extractor.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55

66
"apiReport": {
77
"enabled": true,
8-
"reportFolder": "../../../common/reviews/api"
8+
"reportFolder": "<projectFolder>/docs/review"
99
},
1010

1111
"docModel": {
1212
"enabled": true,
13-
"apiJsonFilePath": "../../../common/temp/api/<unscopedPackageName>.api.json"
13+
"apiJsonFilePath": "<projectFolder>/docs/<unscopedPackageName>.api.json"
1414
},
1515

1616
"dtsRollup": {

packages/api-extractor/src/collector/Collector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import { ReleaseTag } from '@discordjs/api-extractor-model';
55
import * as tsdoc from '@microsoft/tsdoc';
66
import { PackageJsonLookup, Sort, InternalError } from '@rushstack/node-core-library';
7-
import * as ts from 'typescript';
7+
import ts from 'typescript';
88
import { PackageDocComment } from '../aedoc/PackageDocComment.js';
99
import type { AstDeclaration } from '../analyzer/AstDeclaration.js';
1010
import type { AstEntity } from '../analyzer/AstEntity.js';

packages/api-extractor/src/generators/ApiModelGenerator.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import {
3636
Navigation,
3737
} from '@discordjs/api-extractor-model';
3838
import type * as tsdoc from '@microsoft/tsdoc';
39-
import { TSDocParser } from '@microsoft/tsdoc';
4039
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
4140
import { JsonFile, Path } from '@rushstack/node-core-library';
4241
import * as ts from 'typescript';
@@ -220,12 +219,16 @@ export class ApiModelGenerator {
220219

221220
private readonly _apiModel: ApiModel;
222221

222+
private readonly _tsDocParser: tsdoc.TSDocParser;
223+
223224
private readonly _referenceGenerator: DeclarationReferenceGenerator;
224225

225226
public constructor(collector: Collector) {
226227
this._collector = collector;
227228
this._apiModel = new ApiModel();
228229
this._referenceGenerator = new DeclarationReferenceGenerator(collector);
230+
// @ts-expect-error we reuse the private tsdocParser from collector here
231+
this._tsDocParser = collector._tsdocParser;
229232
}
230233

231234
public get apiModel(): ApiModel {
@@ -500,7 +503,7 @@ export class ApiModelGenerator {
500503
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
501504
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
502505
const docComment: tsdoc.DocComment | undefined = parent?.construct
503-
? new TSDocParser().parseString(
506+
? this._tsDocParser.parseString(
504507
`/*+\n * ${fixLinkTags(parent.construct.description)}\n${
505508
parent.construct.params
506509
?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`)
@@ -586,7 +589,7 @@ export class ApiModelGenerator {
586589
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
587590
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
588591
const docComment: tsdoc.DocComment | undefined = jsDoc
589-
? new TSDocParser().parseString(
592+
? this._tsDocParser.parseString(
590593
`/**\n * ${fixLinkTags(jsDoc.description)}\n${jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${
591594
jsDoc.deprecated
592595
? ` * @deprecated ${
@@ -658,7 +661,7 @@ export class ApiModelGenerator {
658661
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
659662
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
660663
const docComment: tsdoc.DocComment | undefined = parent?.construct
661-
? new TSDocParser().parseString(
664+
? this._tsDocParser.parseString(
662665
`/*+\n * ${fixLinkTags(parent.construct.description)}\n${
663666
parent.construct.params
664667
?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`)
@@ -789,7 +792,7 @@ export class ApiModelGenerator {
789792
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
790793
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
791794
const docComment: tsdoc.DocComment | undefined = jsDoc
792-
? new TSDocParser().parseString(
795+
? this._tsDocParser.parseString(
793796
`/**\n * ${fixLinkTags(jsDoc.description)}\n${
794797
jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ??
795798
''
@@ -916,7 +919,7 @@ export class ApiModelGenerator {
916919
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
917920
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
918921
const docComment: tsdoc.DocComment | undefined = jsDoc
919-
? new TSDocParser().parseString(
922+
? this._tsDocParser.parseString(
920923
`/**\n * ${fixLinkTags(jsDoc.description)}\n${jsDoc.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''}${
921924
jsDoc.deprecated
922925
? ` * @deprecated ${
@@ -980,7 +983,7 @@ export class ApiModelGenerator {
980983
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
981984
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
982985
const docComment: tsdoc.DocComment | undefined = jsDoc
983-
? new TSDocParser().parseString(
986+
? this._tsDocParser.parseString(
984987
`/**\n * ${fixLinkTags(jsDoc.description)}\n${
985988
jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ??
986989
''
@@ -1058,7 +1061,7 @@ export class ApiModelGenerator {
10581061
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
10591062
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
10601063
const docComment: tsdoc.DocComment | undefined = jsDoc
1061-
? new TSDocParser().parseString(
1064+
? this._tsDocParser.parseString(
10621065
`/**\n * ${fixLinkTags(jsDoc.description)}\n${
10631066
jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ??
10641067
''
@@ -1166,7 +1169,7 @@ export class ApiModelGenerator {
11661169
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
11671170
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
11681171
const docComment: tsdoc.DocComment | undefined = jsDoc
1169-
? new TSDocParser().parseString(
1172+
? this._tsDocParser.parseString(
11701173
`/**\n * ${fixLinkTags(jsDoc.description)}\n${
11711174
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
11721175
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
@@ -1229,7 +1232,7 @@ export class ApiModelGenerator {
12291232
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
12301233
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
12311234
const docComment: tsdoc.DocComment | undefined = jsDoc
1232-
? new TSDocParser().parseString(
1235+
? this._tsDocParser.parseString(
12331236
`/**\n * ${fixLinkTags(jsDoc.description)}\n${
12341237
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
12351238
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
@@ -1290,7 +1293,7 @@ export class ApiModelGenerator {
12901293
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
12911294
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
12921295
const docComment: tsdoc.DocComment | undefined = jsDoc
1293-
? new TSDocParser().parseString(
1296+
? this._tsDocParser.parseString(
12941297
`/**\n * ${fixLinkTags(jsDoc.description) ?? ''}\n${
12951298
'params' in jsDoc
12961299
? jsDoc.params.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('')
@@ -1425,7 +1428,7 @@ export class ApiModelGenerator {
14251428
});
14261429
}
14271430

1428-
const docComment: tsdoc.DocComment | undefined = new TSDocParser().parseString(
1431+
const docComment: tsdoc.DocComment | undefined = this._tsDocParser.parseString(
14291432
`/**\n * ${fixLinkTags(jsDoc.description)}\n${
14301433
jsDoc.params?.map((param) => ` * @param ${param.name} - ${fixLinkTags(param.description)}\n`).join('') ?? ''
14311434
}${'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''}${

packages/api-extractor/src/generators/ExcerptBuilder.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export class ExcerptBuilder {
135135
return { startIndex: 0, endIndex: 0, typeParameters: [] };
136136
}
137137

138-
public static isPrimitiveKeyword(node: ts.Node): boolean {
138+
private static _isPrimitiveKeyword(node: ts.Node): boolean {
139139
switch (node.kind) {
140140
case ts.SyntaxKind.AnyKeyword:
141141
case ts.SyntaxKind.BigIntKeyword:
@@ -156,6 +156,15 @@ export class ExcerptBuilder {
156156
}
157157
}
158158

159+
private static _isRedundantBarAfterColon(span: Span) {
160+
return (
161+
span.kind === ts.SyntaxKind.BarToken &&
162+
span.previousSibling === undefined &&
163+
(span.parent?.parent?.previousSibling?.kind === ts.SyntaxKind.LessThanToken ||
164+
span.parent?.parent?.previousSibling?.kind === ts.SyntaxKind.ColonToken)
165+
);
166+
}
167+
159168
private static _buildSpan(excerptTokens: IExcerptToken[], span: Span, state: IBuildSpanState): boolean {
160169
if (span.kind === ts.SyntaxKind.JSDocComment) {
161170
// Discard any comments
@@ -174,21 +183,21 @@ export class ExcerptBuilder {
174183
if (span.prefix) {
175184
let canonicalReference: DeclarationReference | undefined;
176185

177-
if (span.kind === ts.SyntaxKind.Identifier) {
178-
const name: ts.Identifier = span.node as ts.Identifier;
186+
if (ts.isIdentifier(span.node)) {
187+
const name: ts.Identifier = span.node;
179188
canonicalReference = state.referenceGenerator.getDeclarationReferenceForIdentifier(name);
180189
}
181190

182191
if (canonicalReference) {
183192
ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Reference, span.prefix, canonicalReference);
184193
} else if (
185-
ExcerptBuilder.isPrimitiveKeyword(span.node) ||
186-
(span.node.kind === ts.SyntaxKind.Identifier &&
194+
ExcerptBuilder._isPrimitiveKeyword(span.node) ||
195+
(ts.isIdentifier(span.node) &&
187196
((ts.isTypeReferenceNode(span.node.parent) && span.node.parent.typeName === span.node) ||
188197
(ts.isTypeParameterDeclaration(span.node.parent) && span.node.parent.name === span.node)))
189198
) {
190199
ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Reference, span.prefix);
191-
} else {
200+
} else if (!ExcerptBuilder._isRedundantBarAfterColon(span)) {
192201
ExcerptBuilder._appendToken(excerptTokens, ExcerptTokenKind.Content, span.prefix);
193202
}
194203

@@ -313,6 +322,12 @@ export class ExcerptBuilder {
313322
!startOrEndIndices.has(currentIndex)
314323
) {
315324
prevToken.text += currentToken.text;
325+
// Remove BarTokens from excerpts if they immediately follow a LessThanToken, e.g. `Promise< | Something>`
326+
// would become `Promise<Something>`
327+
if (/<\s*\|/.test(prevToken.text)) {
328+
prevToken.text = prevToken.text.replace(/<\s*\|\s*/, '<');
329+
}
330+
316331
mergeCount = 1;
317332
} else {
318333
// Otherwise, no merging can occur here. Continue to the next index.

0 commit comments

Comments
 (0)