Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(website): type parameters links, builtin doc links, default values #10515

Merged
merged 5 commits into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/website/src/components/ParameterNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export async function ParameterNode({
{description ? <Badges node={parameter} /> : null}
{parameter.name}
{parameter.isOptional ? '?' : ''}: <ExcerptNode node={parameter.typeExcerpt} version={version} />
{parameter.defaultValue ? ` = ${parameter.defaultValue}` : ''}
</span>
{description && parameter.description?.length ? (
<div className="mt-4 pl-4">
Expand Down
8 changes: 7 additions & 1 deletion apps/website/src/components/PropertyNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ export async function PropertyNode({
<LinkIcon aria-hidden size={16} />
</Link>
{property.displayName}
{property.isOptional ? '?' : ''} : <ExcerptNode node={property.typeExcerpt} version={version} />
{property.isOptional ? '?' : ''} : <ExcerptNode node={property.typeExcerpt} version={version} />{' '}
{property.summary?.defaultValueBlock.length
? `= ${property.summary.defaultValueBlock.reduce(
(acc: string, def: { kind: string; text: string }) => `${acc}${def.text}`,
'',
)}`
: ''}
</span>
</h3>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { IExcerptTokenRange } from './Excerpt.js';
* @public
*/
export interface IApiParameterOptions {
defaultValue: string | undefined;
isOptional: boolean;
isRest: boolean;
parameterName: string;
Expand Down Expand Up @@ -124,6 +125,7 @@ export function ApiParameterListMixin<TBaseClass extends IApiItemConstructor>(
isOptional: Boolean(parameterOptions.isOptional),
isRest: Boolean(parameterOptions.isRest),
parent: this,
defaultValue: parameterOptions.defaultValue,
});

this[_parameters].push(parameter);
Expand Down Expand Up @@ -171,6 +173,7 @@ export function ApiParameterListMixin<TBaseClass extends IApiItemConstructor>(
parameterTypeTokenRange: parameter.parameterTypeExcerpt.tokenRange,
isOptional: parameter.isOptional,
isRest: parameter.isRest,
defaultValue: parameter.defaultValue,
});
}

Expand Down
1 change: 1 addition & 0 deletions packages/api-extractor-model/src/model/ApiPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const MinifyJSONMapping = {
constraintTokenRange: 'ctr',
dependencies: 'dp',
defaultTypeTokenRange: 'dtr',
defaultValue: 'dv',
docComment: 'd',
endIndex: 'en',
excerptTokens: 'ex',
Expand Down
1 change: 1 addition & 0 deletions packages/api-extractor-model/src/model/Deserializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ function mapParam(
startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0),
endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0),
},
defaultValue: param.default,
};
}

Expand Down
7 changes: 7 additions & 0 deletions packages/api-extractor-model/src/model/Parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { Excerpt } from '../mixins/Excerpt.js';
* @public
*/
export interface IParameterOptions {
defaultValue: string | undefined;
isOptional: boolean;
isRest: boolean;
name: string;
Expand Down Expand Up @@ -56,6 +57,11 @@ export class Parameter {
*/
public isRest: boolean;

/**
* The default value for this parameter if optional
*/
public defaultValue: string | undefined;

private readonly _parent: ApiParameterListMixin;

public constructor(options: IParameterOptions) {
Expand All @@ -64,6 +70,7 @@ export class Parameter {
this.isOptional = options.isOptional;
this.isRest = options.isRest;
this._parent = options.parent;
this.defaultValue = options.defaultValue;
}

/**
Expand Down
30 changes: 23 additions & 7 deletions packages/api-extractor/src/generators/ApiModelGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,7 @@ export class ApiModelGenerator {
const parameters: IApiParameterOptions[] = this._captureParameters(
nodesToCapture,
functionDeclaration.parameters,
jsDoc?.params,
);

const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
Expand Down Expand Up @@ -1043,6 +1044,7 @@ export class ApiModelGenerator {
const parameters: IApiParameterOptions[] = this._captureParameters(
nodesToCapture,
methodDeclaration.parameters,
jsDoc?.params,
);

const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
Expand Down Expand Up @@ -1137,7 +1139,11 @@ export class ApiModelGenerator {
methodSignature.typeParameters,
);

const parameters: IApiParameterOptions[] = this._captureParameters(nodesToCapture, methodSignature.parameters);
const parameters: IApiParameterOptions[] = this._captureParameters(
nodesToCapture,
methodSignature.parameters,
jsDoc?.params,
);

const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
Expand Down Expand Up @@ -1342,7 +1348,7 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
`/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}${jsDoc.default ? ` (default: ${this._escapeSpecialChars(jsDoc.default)})` : ''}\n${
`/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}${jsDoc.default ? `\n * @defaultValue ${this._escapeSpecialChars(jsDoc.default)}` : ''}\n${
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
'deprecated' in jsDoc && jsDoc.deprecated
Expand Down Expand Up @@ -1529,6 +1535,7 @@ export class ApiModelGenerator {
},
isOptional: Boolean(parameter.optional),
isRest: parameter.name.startsWith('...'),
defaultValue: parameter.default?.toString(),
});
excerptTokens.push(...newTokens);
excerptTokens.push({
Expand All @@ -1548,6 +1555,7 @@ export class ApiModelGenerator {
},
isOptional: Boolean(parameter.optional),
isRest: parameter.name.startsWith('...'),
defaultValue: parameter.default?.toString(),
});
excerptTokens.push(...newTokens);
excerptTokens.push({
Expand Down Expand Up @@ -1640,6 +1648,7 @@ export class ApiModelGenerator {
private _captureParameters(
nodesToCapture: IExcerptBuilderNodeToCapture[],
parameterNodes: ts.NodeArray<ts.ParameterDeclaration>,
jsDoc?: DocgenParamJson[] | undefined,
): IApiParameterOptions[] {
const parameters: IApiParameterOptions[] = [];
for (const parameter of parameterNodes) {
Expand All @@ -1650,6 +1659,9 @@ export class ApiModelGenerator {
parameterTypeTokenRange,
isOptional: this._collector.typeChecker.isOptionalParameter(parameter),
isRest: Boolean(parameter.dotDotDotToken),
defaultValue:
parameter.initializer?.getText() ??
jsDoc?.find((param) => param.name === parameter.name.getText().trim())?.default?.toString(),
});
}

Expand Down Expand Up @@ -1753,7 +1765,7 @@ export class ApiModelGenerator {
return input;
}

return input.replaceAll(/(?<char>[{}])/g, '\\$<char>');
return input.replaceAll(/(?<char>[@{}])/g, '\\$<char>');
}

private _fixLinkTags(input?: string): string | undefined {
Expand Down Expand Up @@ -1848,7 +1860,7 @@ export class ApiModelGenerator {
isOptional: Boolean(prop.nullable),
isReadonly: Boolean(prop.readonly),
docComment: this._tsDocParser.parseString(
`/**\n * ${this._fixLinkTags(prop.description) ?? ''}${prop.default ? ` (default: ${this._escapeSpecialChars(prop.default)})` : ''}\n${
`/**\n * ${this._fixLinkTags(prop.description) ?? ''}\n${prop.default ? ` * @defaultValue ${this._escapeSpecialChars(prop.default)}\n` : ''}${
prop.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''
}${prop.readonly ? ' * @readonly\n' : ''} */`,
).docComment,
Expand All @@ -1860,7 +1872,7 @@ export class ApiModelGenerator {
}${prop.name} :`,
},
...mappedVarType,
{ kind: ExcerptTokenKind.Content, text: ';' },
{ kind: ExcerptTokenKind.Content, text: `${prop.default ? ` = ${prop.default}` : ''};` },
],
propertyTypeTokenRange: { startIndex: 1, endIndex: 1 + mappedVarType.length },
releaseTag: prop.access === 'private' ? ReleaseTag.Internal : ReleaseTag.Public,
Expand All @@ -1883,6 +1895,7 @@ export class ApiModelGenerator {
startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0),
endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0),
},
defaultValue: param.default?.toString(),
};
}

Expand All @@ -1907,7 +1920,7 @@ export class ApiModelGenerator {
excerptTokens.push(...newTokens);
excerptTokens.push({
kind: ExcerptTokenKind.Content,
text: `, ${method.params![index + 1]!.name}${
text: `${method.params![index]!.default ? ` = ${method.params![index]!.default}` : ''}, ${method.params![index + 1]!.name}${
method.params![index + 1]!.nullable || method.params![index + 1]!.optional ? '?' : ''
}: `,
});
Expand All @@ -1917,7 +1930,10 @@ export class ApiModelGenerator {
const newTokens = this._mapVarType(method.params[method.params.length - 1]!.type);
paramTokens.push(newTokens.length);
excerptTokens.push(...newTokens);
excerptTokens.push({ kind: ExcerptTokenKind.Content, text: `): ` });
excerptTokens.push({
kind: ExcerptTokenKind.Content,
text: `${method.params![method.params.length - 1]!.default ? ` = ${method.params![method.params.length - 1]!.default}` : ''}): `,
});
}

const returnTokens = this._mapVarType(method.returns?.[0] ?? []);
Expand Down
4 changes: 2 additions & 2 deletions packages/discord.js/src/util/Options.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const { version } = require('../../package.json');
* @property {MessageMentionOptions} [allowedMentions] The default value for {@link BaseMessageOptions#allowedMentions}
* @property {Partials[]} [partials] Structures allowed to be partial. This means events can be emitted even when
* they're missing all the data for a particular structure. See the "Partial Structures" topic on the
* [guide](https://discordjs.guide/popular-topics/partials.html) for some
* {@link https://discordjs.guide/popular-topics/partials.html guide} for some
* important usage information, as partials require you to put checks in place when handling data.
* @property {boolean} [failIfNotExists=true] The default value for {@link MessageReplyOptions#failIfNotExists}
* @property {PresenceData} [presence] Presence data to use upon login
Expand All @@ -37,7 +37,7 @@ const { version } = require('../../package.json');
* @property {WebSocketManagerOptions} [ws] Options for the WebSocketManager
* @property {RESTOptions} [rest] Options for the REST manager
* @property {Function} [jsonTransformer] A function used to transform outgoing json data
* @property {boolean} [enforceNonce=false] The default value for {@link MessageReplyOptions#enforceNonce}
* @property {boolean} [enforceNonce=false] The default value for {@link MessageCreateOptions#enforceNonce}
*/

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/discord.js/typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5731,7 +5731,7 @@ export type GuildAuditLogsResolvable = AuditLogEvent | null;
export type GuildAuditLogsTargetType = GuildAuditLogsTypes[keyof GuildAuditLogsTypes][0] | 'All' | 'Unknown';

export type GuildAuditLogsTargets = {
[key in GuildAuditLogsTargetType]: GuildAuditLogsTargetType;
[Key in GuildAuditLogsTargetType]: GuildAuditLogsTargetType;
};

export type GuildBanResolvable = GuildBan | UserResolvable;
Expand Down
109 changes: 109 additions & 0 deletions packages/scripts/src/builtinDocumentationLinks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
export const BuiltinDocumentationLinks = {
// Built-in types
bigint: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/BigInt',
boolean: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean',
null: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/null',
number: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number',
string: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String',
symbol: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol',
undefined: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined',

// Built-in classes
AbortSignal: 'https://developer.mozilla.org/docs/Web/API/AbortSignal',
Agent: 'https://undici.nodejs.org/#/docs/api/Agent',
Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array',
ArrayBuffer: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer',
AsyncGenerator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator',
AsyncIterable: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols',
AsyncIterableIterator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols',
Buffer: 'https://nodejs.org/api/buffer.html#class-buffer',
ChildProcess: 'https://nodejs.org/api/child_process.html#class-childprocess',
Date: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date',
Dispatcher: 'https://undici.nodejs.org/#/docs/api/Dispatcher',
Error: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error',
Function: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function',
Generator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Generator',
IncomingMessage: 'https://nodejs.org/api/http.html#class-httpincomingmessage',
Iterable: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols',
IterableIterator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols',
Iterator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Iterator',
Map: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map',
MessagePort: 'https://nodejs.org/api/worker_threads.html#class-messageport',
Promise: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise',
RangeError: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError',
Readable: 'https://nodejs.org/api/stream.html#class-streamreadable',
ReadableStream: 'https://developer.mozilla.org/docs/Web/API/ReadableStream',
RegExp: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp',
Response: 'https://developer.mozilla.org/docs/Web/API/Response',
ServerResponse: 'https://nodejs.org/api/http.html#class-httpserverresponse',
Set: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Set',
Stream: 'https://nodejs.org/api/stream.html#stream',
SymbolConstructor: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol',
TypeError: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError',
URL: 'https://developer.mozilla.org/docs/Web/API/URL',
URLSearchParams: 'https://developer.mozilla.org/docs/Web/API/URLSearchParams',
WeakMap: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakMap',
WeakRef: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakRef',
WeakSet: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakSet',
WebSocket: 'https://developer.mozilla.org/docs/Web/API/WebSocket',
Worker: 'https://nodejs.org/api/worker_threads.html#class-worker',
'NodeJS.Timeout': 'https://nodejs.org/api/timers.html#class-timeout',

// Typed arrays
BigInt64Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array',
BigUint64Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array',
Float32Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Float32Array',
Float64Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Float64Array',
Int16Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Int16Array',
Int32Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Int32Array',
Int8Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Int8Array',
Uint16Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array',
Uint32Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array',
Uint8Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array',
Uint8ClampedArray: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray',

// TypeScript types
any: 'https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any',
keyof: 'https://www.typescriptlang.org/docs/handbook/2/keyof-types.html',
never: 'https://www.typescriptlang.org/docs/handbook/2/functions.html#never',
object: 'https://www.typescriptlang.org/docs/handbook/2/functions.html#object',
ReadonlyArray: 'https://www.typescriptlang.org/docs/handbook/2/objects.html#the-readonlyarray-type',
ReadonlyMap:
'https://github.com/microsoft/TypeScript/blob/1416053b9e85ca2344a7a6aa10456d633ea1cd65/src/lib/es2015.collection.d.ts#L38-L43',
ReadonlySet:
'https://github.com/microsoft/TypeScript/blob/1416053b9e85ca2344a7a6aa10456d633ea1cd65/src/lib/es2015.collection.d.ts#L104-L108',
unknown: 'https://www.typescriptlang.org/docs/handbook/2/functions.html#unknown',
this: 'https://www.typescriptlang.org/docs/handbook/2/classes.html#this-types',
typeof: 'https://www.typescriptlang.org/docs/handbook/2/typeof-types.html',
void: 'https://www.typescriptlang.org/docs/handbook/2/functions.html#void',

// TypeScript utility types
Awaited: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#awaitedtype',
Partial: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype',
Required: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype',
Readonly: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype',
Record: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type',
Pick: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys',
Omit: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys',
Exclude: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers',
Extract: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union',
NonNullable: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype',
Parameters: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype',
ConstructorParameters: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#constructorparameterstype',
ReturnType: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype',
InstanceType: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype',
ThisParameterType: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#thisparametertypetype',
OmitThisParameter: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#omitthisparametertype',
ThisType: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#thistypetype',
Uppercase: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#uppercasestringtype',
Lowercase: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#lowercasestringtype',
Capitalize: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#capitalizestringtype',
Uncapitalize: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#uncapitalizestringtype',

// External Libraries
AsyncEventEmitter: 'https://github.com/vladfrangu/async_event_emitter',
AsyncQueue: 'https://www.sapphirejs.dev/docs/Documentation/api-utilities/classes/sapphire_async_queue.AsyncQueue',
Redis: 'https://redis.github.io/ioredis/classes/Redis.html',
'prism.opus.Encoder': 'https://amishshah.github.io/prism-media/opus.Encoder.html',
'prism.VolumeTransformer': 'https://amishshah.github.io/prism-media/core.VolumeTransformer.html',
} as const;
Loading