From 34531c45e3e00ab0ab14f703e25b5c32435d9a3d Mon Sep 17 00:00:00 2001 From: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com> Date: Wed, 6 Jul 2022 11:37:33 -0400 Subject: [PATCH] feat(website): add support for type parameter documentation (#8237) --- packages/website/src/DocModel/DocClass.ts | 8 +++- packages/website/src/DocModel/DocFunction.ts | 12 +++++- packages/website/src/DocModel/DocInterface.ts | 6 ++- packages/website/src/DocModel/DocMethod.ts | 11 +++++- .../src/DocModel/DocMethodSignature.ts | 11 +++++- packages/website/src/DocModel/DocTypeAlias.ts | 5 ++- .../website/src/components/DocContainer.tsx | 11 +++++- .../website/src/components/TypeParamTable.tsx | 39 +++++++++++++++++++ .../website/src/components/model/Class.tsx | 8 +++- .../website/src/components/model/Function.tsx | 8 +++- .../src/components/model/Interface.tsx | 8 +++- .../src/components/model/TypeAlias.tsx | 8 +++- packages/website/src/util/api-model.server.ts | 2 +- packages/website/src/util/parse.server.ts | 20 ++++++++++ 14 files changed, 145 insertions(+), 12 deletions(-) create mode 100644 packages/website/src/components/TypeParamTable.tsx diff --git a/packages/website/src/DocModel/DocClass.ts b/packages/website/src/DocModel/DocClass.ts index cc37a0bbb..d12430c5b 100644 --- a/packages/website/src/DocModel/DocClass.ts +++ b/packages/website/src/DocModel/DocClass.ts @@ -8,24 +8,29 @@ import { import { DocItem } from './DocItem'; import { DocMethod } from './DocMethod'; import { DocProperty } from './DocProperty'; -import { type TokenDocumentation, genToken } from '~/util/parse.server'; +import { type TokenDocumentation, genToken, TypeParameterData, generateTypeParamData } from '~/util/parse.server'; export class DocClass extends DocItem { public readonly extendsTokens: TokenDocumentation[] | null; public readonly implementsTokens: TokenDocumentation[][]; public readonly methods: DocMethod[] = []; public readonly properties: DocProperty[] = []; + public readonly typeParameters: TypeParameterData[] = []; public constructor(model: ApiModel, item: ApiClass) { super(model, item); const extendsExcerpt = item.extendsType?.excerpt; + this.extendsTokens = extendsExcerpt ? extendsExcerpt.spannedTokens.map((token) => genToken(this.model, token)) : null; + this.implementsTokens = item.implementsTypes.map((excerpt) => excerpt.excerpt.spannedTokens.map((token) => genToken(this.model, token)), ); + this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(model, typeParam)); + for (const member of item.members) { switch (member.kind) { case ApiItemKind.Method: @@ -47,6 +52,7 @@ export class DocClass extends DocItem { implementsTokens: this.implementsTokens, methods: this.methods.map((method) => method.toJSON()), properties: this.properties.map((prop) => prop.toJSON()), + typeParameters: this.typeParameters, }; } } diff --git a/packages/website/src/DocModel/DocFunction.ts b/packages/website/src/DocModel/DocFunction.ts index 5a3fe3c25..7b87a5c11 100644 --- a/packages/website/src/DocModel/DocFunction.ts +++ b/packages/website/src/DocModel/DocFunction.ts @@ -1,17 +1,26 @@ import type { ApiFunction, ApiModel } from '@microsoft/api-extractor-model'; import { DocItem } from './DocItem'; -import { type ParameterDocumentation, type TokenDocumentation, genParameter, genToken } from '~/util/parse.server'; +import { + type ParameterDocumentation, + type TokenDocumentation, + genParameter, + genToken, + type TypeParameterData, + generateTypeParamData, +} from '~/util/parse.server'; export class DocFunction extends DocItem { public readonly parameters: ParameterDocumentation[]; public readonly returnTypeTokens: TokenDocumentation[]; public readonly overloadIndex: number; + public readonly typeParameters: TypeParameterData[] = []; public constructor(model: ApiModel, item: ApiFunction) { super(model, item); this.parameters = item.parameters.map((param) => genParameter(this.model, param)); this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token)); this.overloadIndex = item.overloadIndex; + this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(model, typeParam)); } public override toJSON() { @@ -20,6 +29,7 @@ export class DocFunction extends DocItem { parameters: this.parameters, returnTypeTokens: this.returnTypeTokens, overloadIndex: this.overloadIndex, + typeParameters: this.typeParameters, }; } } diff --git a/packages/website/src/DocModel/DocInterface.ts b/packages/website/src/DocModel/DocInterface.ts index 1771ec412..c02f59b2c 100644 --- a/packages/website/src/DocModel/DocInterface.ts +++ b/packages/website/src/DocModel/DocInterface.ts @@ -2,12 +2,13 @@ import { DocItem } from './DocItem'; import { DocMethodSignature } from './DocMethodSignature'; import { DocProperty } from './DocProperty'; import { ApiInterface, ApiItemKind, ApiMethodSignature, ApiModel, ApiPropertySignature } from '~/api-extractor.server'; -import { type TokenDocumentation, genToken } from '~/util/parse.server'; +import { type TokenDocumentation, genToken, type TypeParameterData, generateTypeParamData } from '~/util/parse.server'; export class DocInterface extends DocItem { public readonly extendsTokens: TokenDocumentation[][] | null; public readonly methods: DocMethodSignature[] = []; public readonly properties: DocProperty[] = []; + public readonly typeParameters: TypeParameterData[] = []; public constructor(model: ApiModel, item: ApiInterface) { super(model, item); @@ -16,6 +17,8 @@ export class DocInterface extends DocItem { excerpt.excerpt.spannedTokens.map((token) => genToken(this.model, token)), ); + this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(this.model, typeParam)); + for (const member of item.members) { switch (member.kind) { case ApiItemKind.MethodSignature: @@ -36,6 +39,7 @@ export class DocInterface extends DocItem { extendsTokens: this.extendsTokens, methods: this.methods.map((method) => method.toJSON()), properties: this.properties.map((prop) => prop.toJSON()), + typeParameters: this.typeParameters, }; } } diff --git a/packages/website/src/DocModel/DocMethod.ts b/packages/website/src/DocModel/DocMethod.ts index a222405db..7c6afb11f 100644 --- a/packages/website/src/DocModel/DocMethod.ts +++ b/packages/website/src/DocModel/DocMethod.ts @@ -1,7 +1,14 @@ import type { ApiMethod, ApiModel } from '@microsoft/api-extractor-model'; import { DocItem } from './DocItem'; import { Visibility } from './Visibility'; -import { type ParameterDocumentation, type TokenDocumentation, genParameter, genToken } from '~/util/parse.server'; +import { + type ParameterDocumentation, + type TokenDocumentation, + genParameter, + genToken, + generateTypeParamData, + TypeParameterData, +} from '~/util/parse.server'; export class DocMethod extends DocItem { public readonly parameters: ParameterDocumentation[]; @@ -10,6 +17,7 @@ export class DocMethod extends DocItem { public readonly visibility: Visibility; public readonly returnTypeTokens: TokenDocumentation[]; public readonly overloadIndex: number; + public readonly typeParameters: TypeParameterData[] = []; public constructor(model: ApiModel, item: ApiMethod) { super(model, item); @@ -19,6 +27,7 @@ export class DocMethod extends DocItem { this.visibility = item.isProtected ? Visibility.Protected : Visibility.Public; this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token)); this.overloadIndex = item.overloadIndex; + this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(this.model, typeParam)); } public override toJSON() { diff --git a/packages/website/src/DocModel/DocMethodSignature.ts b/packages/website/src/DocModel/DocMethodSignature.ts index c83b33d95..5f44439da 100644 --- a/packages/website/src/DocModel/DocMethodSignature.ts +++ b/packages/website/src/DocModel/DocMethodSignature.ts @@ -1,12 +1,20 @@ import type { ApiMethodSignature, ApiModel } from '@microsoft/api-extractor-model'; import { DocItem } from './DocItem'; -import { type ParameterDocumentation, type TokenDocumentation, genParameter, genToken } from '~/util/parse.server'; +import { + type ParameterDocumentation, + type TokenDocumentation, + genParameter, + genToken, + generateTypeParamData, + type TypeParameterData, +} from '~/util/parse.server'; export class DocMethodSignature extends DocItem { public readonly parameters: ParameterDocumentation[]; public readonly optional: boolean; public readonly returnTypeTokens: TokenDocumentation[]; public readonly overloadIndex: number; + public readonly typeParameters: TypeParameterData[] = []; public constructor(model: ApiModel, item: ApiMethodSignature) { super(model, item); @@ -14,6 +22,7 @@ export class DocMethodSignature extends DocItem { this.optional = item.isOptional; this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token)); this.overloadIndex = item.overloadIndex; + this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(this.model, typeParam)); } public override toJSON() { diff --git a/packages/website/src/DocModel/DocTypeAlias.ts b/packages/website/src/DocModel/DocTypeAlias.ts index 61f3df024..edf093c53 100644 --- a/packages/website/src/DocModel/DocTypeAlias.ts +++ b/packages/website/src/DocModel/DocTypeAlias.ts @@ -1,19 +1,22 @@ import type { ApiModel, ApiTypeAlias } from '@microsoft/api-extractor-model'; import { DocItem } from './DocItem'; -import { type TokenDocumentation, genToken } from '~/util/parse.server'; +import { type TokenDocumentation, genToken, generateTypeParamData, type TypeParameterData } from '~/util/parse.server'; export class DocTypeAlias extends DocItem { public readonly typeTokens: TokenDocumentation[]; + public readonly typeParameters: TypeParameterData[] = []; public constructor(model: ApiModel, item: ApiTypeAlias) { super(model, item); this.typeTokens = item.typeExcerpt.spannedTokens.map((token) => genToken(model, token)); + this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(this.model, typeParam)); } public override toJSON() { return { ...super.toJSON(), typeTokens: this.typeTokens, + typeParameters: this.typeParameters, }; } } diff --git a/packages/website/src/components/DocContainer.tsx b/packages/website/src/components/DocContainer.tsx index 5cb7a8964..70455dfe9 100644 --- a/packages/website/src/components/DocContainer.tsx +++ b/packages/website/src/components/DocContainer.tsx @@ -1,6 +1,8 @@ import { VscSymbolClass, VscSymbolMethod, VscSymbolEnum, VscSymbolInterface, VscSymbolVariable } from 'react-icons/vsc'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { vs } from 'react-syntax-highlighter/dist/cjs/styles/prism'; +import { TypeParamTable } from './TypeParamTable'; +import type { TypeParameterData } from '~/util/parse.server'; export interface DocContainerProps { name: string; @@ -8,6 +10,7 @@ export interface DocContainerProps { excerpt: string; summary?: string | null; children?: JSX.Element; + typeParams?: TypeParameterData[]; } const symbolClass = 'mr-2'; @@ -20,7 +23,7 @@ const icons = { TypeAlias: , }; -export function DocContainer({ name, kind, excerpt, summary, children }: DocContainerProps) { +export function DocContainer({ name, kind, excerpt, summary, typeParams, children }: DocContainerProps) { return (

@@ -31,6 +34,12 @@ export function DocContainer({ name, kind, excerpt, summary, children }: DocCont {excerpt} + {typeParams?.length ? ( + <> +

Type Parameters

+ + + ) : null}

Summary

{summary ?? 'No summary provided.'}

{children} diff --git a/packages/website/src/components/TypeParamTable.tsx b/packages/website/src/components/TypeParamTable.tsx new file mode 100644 index 000000000..f0d09d37a --- /dev/null +++ b/packages/website/src/components/TypeParamTable.tsx @@ -0,0 +1,39 @@ +import type { TypeParameterData } from '~/util/parse.server'; +import { constructHyperlinkedText } from '~/util/util'; + +export interface TableProps { + data: TypeParameterData[]; +} + +export function TypeParamTable({ data }: TableProps) { + return ( +
+ + + + + + + + + + + + {data.map((parameter) => ( + + + + + + + + ))} + +
NameConstraintOptionalDefaultDescription
{parameter.name} + {constructHyperlinkedText(parameter.constraintTokens)} + {parameter.optional ? 'Yes' : 'No'} + {constructHyperlinkedText(parameter.defaultTokens)} + None
+
+ ); +} diff --git a/packages/website/src/components/model/Class.tsx b/packages/website/src/components/model/Class.tsx index cc48ba408..c011f3a71 100644 --- a/packages/website/src/components/model/Class.tsx +++ b/packages/website/src/components/model/Class.tsx @@ -9,7 +9,13 @@ export interface ClassProps { export function Class({ data }: ClassProps) { return ( - + <> {data.properties.length ? : null} {data.methods.length ? : null} diff --git a/packages/website/src/components/model/Function.tsx b/packages/website/src/components/model/Function.tsx index ebe4d2cf4..5119a655c 100644 --- a/packages/website/src/components/model/Function.tsx +++ b/packages/website/src/components/model/Function.tsx @@ -8,7 +8,13 @@ export interface FunctionProps { export function Function({ data }: FunctionProps) { return ( - + ); diff --git a/packages/website/src/components/model/Interface.tsx b/packages/website/src/components/model/Interface.tsx index 636684045..12d15ec63 100644 --- a/packages/website/src/components/model/Interface.tsx +++ b/packages/website/src/components/model/Interface.tsx @@ -9,7 +9,13 @@ export interface InterfaceProps { export function Interface({ data }: InterfaceProps) { return ( - + <> {data.properties.length ? : null} {data.methods.length ? : null} diff --git a/packages/website/src/components/model/TypeAlias.tsx b/packages/website/src/components/model/TypeAlias.tsx index 2805b9342..d4c77e6d6 100644 --- a/packages/website/src/components/model/TypeAlias.tsx +++ b/packages/website/src/components/model/TypeAlias.tsx @@ -7,7 +7,13 @@ export interface TypeAliasProps { export function TypeAlias({ data }: TypeAliasProps) { return ( - +
WIP
); diff --git a/packages/website/src/util/api-model.server.ts b/packages/website/src/util/api-model.server.ts index 60e39d8f9..b764c8ae8 100644 --- a/packages/website/src/util/api-model.server.ts +++ b/packages/website/src/util/api-model.server.ts @@ -19,5 +19,5 @@ export function createApiModel(data: any) { tsdocConfiguration, }) as ApiPackage; model.addMember(apiPackage); - return apiPackage as unknown as ApiModel; + return model; } diff --git a/packages/website/src/util/parse.server.ts b/packages/website/src/util/parse.server.ts index 3858311a8..3da4b6123 100644 --- a/packages/website/src/util/parse.server.ts +++ b/packages/website/src/util/parse.server.ts @@ -10,6 +10,7 @@ import { type ApiPropertyItem, type ExcerptToken, type Parameter, + type TypeParameter, } from '@microsoft/api-extractor-model'; import type { DocNode, DocParagraph, DocPlainText } from '@microsoft/tsdoc'; @@ -167,3 +168,22 @@ export function getMembers(pkg: ApiPackage) { path: generatePath(member.getHierarchy()), })); } + +export interface TypeParameterData { + name: string; + constraintTokens: TokenDocumentation[]; + defaultTokens: TokenDocumentation[]; + optional: boolean; +} + +export function generateTypeParamData(model: ApiModel, typeParam: TypeParameter): TypeParameterData { + const constraintTokens = typeParam.constraintExcerpt.spannedTokens.map((token) => genToken(model, token)); + const defaultTokens = typeParam.defaultTypeExcerpt.spannedTokens.map((token) => genToken(model, token)); + + return { + name: typeParam.name, + constraintTokens, + defaultTokens, + optional: typeParam.isOptional, + }; +}