From 5995e0c7c0b2c6774961d6d069fd0b791fcc6b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20=C5=BDilinskas?= Date: Thu, 28 Dec 2017 13:36:56 +0200 Subject: [PATCH 1/6] Added ApiClassPlugin (WIP). --- packages/ts-docs-gen/examples/simple/index.ts | 26 +++--- packages/ts-docs-gen/src/contracts/plugin.ts | 9 +- packages/ts-docs-gen/src/default-plugins.ts | 4 +- packages/ts-docs-gen/src/generator-helpers.ts | 19 ++++- .../src/plugins/api-class-plugin.ts | 85 +++++++++++++++++++ 5 files changed, 127 insertions(+), 16 deletions(-) create mode 100644 packages/ts-docs-gen/src/plugins/api-class-plugin.ts diff --git a/packages/ts-docs-gen/examples/simple/index.ts b/packages/ts-docs-gen/examples/simple/index.ts index e01fe1db..e3c82068 100644 --- a/packages/ts-docs-gen/examples/simple/index.ts +++ b/packages/ts-docs-gen/examples/simple/index.ts @@ -79,11 +79,11 @@ // anotherProperty: number; // } -export function MyFunction(): T { - return { - myProperty: "sampleString" - } as T; -} +// export function MyFunction(): T { +// return { +// myProperty: "sampleString" +// } as T; +// } // export interface MyInterface { // (param1: TValue, param2: TValue): boolean; @@ -203,10 +203,14 @@ export function MyFunction { IsPluginResultExists: IsPluginResultExistsHandler; } -export interface PluginResult { - Reference: ApiItemReference; - ApiItem: TKind; +export interface PluginResultData { /** * All headings used in `Result` with ApiItemIds. */ @@ -47,6 +45,11 @@ export interface PluginResult { Members?: PluginMember[]; } +export interface PluginResult extends PluginResultData { + Reference: ApiItemReference; + ApiItem: TKind; +} + export interface Plugin { SupportedApiItemKinds(): SupportedApiItemKindType[]; CheckApiItem(item: TKind): boolean; diff --git a/packages/ts-docs-gen/src/default-plugins.ts b/packages/ts-docs-gen/src/default-plugins.ts index d7541d65..17149fbc 100644 --- a/packages/ts-docs-gen/src/default-plugins.ts +++ b/packages/ts-docs-gen/src/default-plugins.ts @@ -4,6 +4,7 @@ import { ApiEnumPlugin } from "./plugins/api-enum-plugin"; import { ApiFunctionPlugin } from "./plugins/api-function-plugin"; import { ApiTypePlugin } from "./plugins/api-type-plugin"; import { ApiNamespacePlugin } from "./plugins/api-namespace-plugin"; +import { ApiClassPlugin } from "./plugins/api-class-plugin"; export const DefaultPlugins = [ new ApiSourceFilePlugin(), @@ -11,5 +12,6 @@ export const DefaultPlugins = [ new ApiEnumPlugin(), new ApiFunctionPlugin(), new ApiTypePlugin(), - new ApiNamespacePlugin() + new ApiNamespacePlugin(), + new ApiClassPlugin() ]; diff --git a/packages/ts-docs-gen/src/generator-helpers.ts b/packages/ts-docs-gen/src/generator-helpers.ts index 53eb754d..6baae1c4 100644 --- a/packages/ts-docs-gen/src/generator-helpers.ts +++ b/packages/ts-docs-gen/src/generator-helpers.ts @@ -4,7 +4,7 @@ import { MarkdownGenerator, MarkdownBuilder, Contracts as MarkdownContracts } fr import * as path from "path"; import { ApiItemReference } from "./contracts/api-item-reference"; -import { ApiItemKindsAdditional } from "./contracts/plugin"; +import { ApiItemKindsAdditional, PluginResultData } from "./contracts/plugin"; import { Logger } from "./utils/logger"; export namespace GeneratorHelpers { @@ -344,4 +344,21 @@ export namespace GeneratorHelpers { export function StandardisePath(pathString: string): string { return pathString.split(path.sep).join("/"); } + + export function MergePluginResultData(a: T, b: PluginResultData): T { + a.Headings = a.Headings.concat(b.Headings); + a.Members = (a.Members || []).concat(b.Members || []); + a.Result = a.Result.concat(b.Result); + a.UsedReferences = a.UsedReferences.concat(b.UsedReferences); + + return a; + } + + export function GetDefaultPluginResultData(): PluginResultData { + return { + Headings: [], + Result: [], + UsedReferences: [] + }; + } } diff --git a/packages/ts-docs-gen/src/plugins/api-class-plugin.ts b/packages/ts-docs-gen/src/plugins/api-class-plugin.ts new file mode 100644 index 00000000..39a68c48 --- /dev/null +++ b/packages/ts-docs-gen/src/plugins/api-class-plugin.ts @@ -0,0 +1,85 @@ +import { Contracts } from "ts-extractor"; +import { MarkdownBuilder } from "@simplrjs/markdown"; +import * as path from "path"; + +import { GeneratorHelpers } from "../generator-helpers"; +import { + Plugin, + SupportedApiItemKindType, + PluginOptions, + PluginResult, + PluginResultData +} from "../contracts/plugin"; + +export class ApiClassPlugin implements Plugin { + public SupportedApiItemKinds(): SupportedApiItemKindType[] { + return [GeneratorHelpers.ApiItemKinds.Class]; + } + + public CheckApiItem(item: Contracts.ApiItemDto): boolean { + return true; + } + + private renderMembers(data: PluginOptions): PluginResultData { + const references = GeneratorHelpers.GetApiItemReferences(data.ExtractedData, data.ApiItem.Members); + const renderedItems = references.map(x => data.GetItemPluginResult(x)); + const pluginResultData = GeneratorHelpers.GetDefaultPluginResultData(); + const builder = new MarkdownBuilder(); + + const list: Array<[Contracts.ApiItemKinds, string]> = [ + [Contracts.ApiItemKinds.Index, "Index"], + [Contracts.ApiItemKinds.ClassConstructor, "Constructor"], + [Contracts.ApiItemKinds.ClassMethod, "Methods"], + [Contracts.ApiItemKinds.ClassProperty, "Properties"] + ]; + + for (const [kind, heading] of list) { + const pluginResultsByKind = renderedItems.filter(x => x.ApiItem.ApiKind === kind); + + if (pluginResultsByKind.length > 0) { + builder + .Header(heading, 2) + .EmptyLine(); + + for (const item of pluginResultsByKind) { + GeneratorHelpers.MergePluginResultData(pluginResultData, item); + + builder + .Text(item.Result) + .EmptyLine(); + } + } + } + + pluginResultData.Result = builder.GetOutput(); + return pluginResultData; + } + + public Render(data: PluginOptions): PluginResult { + const pluginResult: PluginResult = { + ApiItem: data.ApiItem, + Reference: data.Reference, + ...GeneratorHelpers.GetDefaultPluginResultData() + }; + const heading = path.basename(data.ApiItem.Name, path.extname(data.ApiItem.Name)); + pluginResult.Headings = [ + { + Heading: heading, + ApiItemId: data.Reference.Id + } + ]; + + // Header + const builder = new MarkdownBuilder() + .Header(heading, 1) + .EmptyLine() + .Text(GeneratorHelpers.RenderApiItemMetadata(data.ApiItem)); + pluginResult.Result = builder.GetOutput(); + + // ApiMembers + const members = this.renderMembers(data); + GeneratorHelpers.MergePluginResultData(pluginResult, members); + + return pluginResult; + } +} From d5e3b8062035c0345aab5e6575da623f1092f2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20=C5=BDilinskas?= Date: Thu, 28 Dec 2017 14:04:51 +0200 Subject: [PATCH 2/6] Added ClassToString function. --- packages/ts-docs-gen/src/generator-helpers.ts | 37 +++++++++++++++++++ .../src/plugins/api-class-plugin.ts | 10 ++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/ts-docs-gen/src/generator-helpers.ts b/packages/ts-docs-gen/src/generator-helpers.ts index 6baae1c4..ed2f39fc 100644 --- a/packages/ts-docs-gen/src/generator-helpers.ts +++ b/packages/ts-docs-gen/src/generator-helpers.ts @@ -306,6 +306,43 @@ export namespace GeneratorHelpers { return `${apiItem.Name}${$extends}${defaultType}`; } + export function ClassToString( + apiItem: Contracts.ApiClassDto, + typeParameters?: Contracts.ApiTypeParameterDto[], + alias?: string + ): string { + const name = alias || apiItem.Name; + // Abstract + const abstract = apiItem.IsAbstract ? "abstract " : ""; + + // TypeParameters + let typeParametersString: string; + if (typeParameters != null && typeParameters.length > 0) { + const params: string[] = typeParameters.map(TypeParameterToString); + typeParametersString = `<${params.join(", ")}>`; + } else { + typeParametersString = ""; + } + + // Extends + let extendsString: string; + if (apiItem.Extends != null) { + extendsString = ` extends ${apiItem.Extends.Text}`; + } else { + extendsString = ""; + } + + // Implements + let implementsString: string; + if (apiItem.Implements != null && apiItem.Implements.length > 0) { + implementsString = ` implements ${apiItem.Implements.map(x => x.Text).join(", ")}`; + } else { + implementsString = ""; + } + + return `${abstract}class ${name}${typeParametersString}${extendsString}${implementsString}`; + } + export function ApiFunctionToSimpleString( alias: string, apiItem: Contracts.ApiFunctionDto, diff --git a/packages/ts-docs-gen/src/plugins/api-class-plugin.ts b/packages/ts-docs-gen/src/plugins/api-class-plugin.ts index 39a68c48..f69311c3 100644 --- a/packages/ts-docs-gen/src/plugins/api-class-plugin.ts +++ b/packages/ts-docs-gen/src/plugins/api-class-plugin.ts @@ -56,6 +56,9 @@ export class ApiClassPlugin implements Plugin { } public Render(data: PluginOptions): PluginResult { + const typeParameters = GeneratorHelpers + .GetApiItemsFromReference(data.ApiItem.TypeParameters, data.ExtractedData); + const pluginResult: PluginResult = { ApiItem: data.ApiItem, Reference: data.Reference, @@ -73,7 +76,12 @@ export class ApiClassPlugin implements Plugin { const builder = new MarkdownBuilder() .Header(heading, 1) .EmptyLine() - .Text(GeneratorHelpers.RenderApiItemMetadata(data.ApiItem)); + .Text(GeneratorHelpers.RenderApiItemMetadata(data.ApiItem)) + .Code(GeneratorHelpers.ClassToString( + data.ApiItem, + typeParameters, + data.Reference.Alias + ), GeneratorHelpers.DEFAULT_CODE_OPTIONS); pluginResult.Result = builder.GetOutput(); // ApiMembers From 1e08b088d2564a90ffec61b6de148211cbf504bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20=C5=BDilinskas?= Date: Thu, 28 Dec 2017 15:13:27 +0200 Subject: [PATCH 3/6] Added ClassConstructorPlugin. --- .../examples/simple/docs/api/index.md | 21 +----- .../examples/simple/docs/api/index/hello.md | 25 +++++++ packages/ts-docs-gen/examples/simple/index.ts | 14 +++- packages/ts-docs-gen/src/default-plugins.ts | 4 +- packages/ts-docs-gen/src/generator-helpers.ts | 34 +++++++++ .../plugins/api-class-constructor-plugin.ts | 73 +++++++++++++++++++ 6 files changed, 151 insertions(+), 20 deletions(-) create mode 100644 packages/ts-docs-gen/examples/simple/docs/api/index/hello.md create mode 100644 packages/ts-docs-gen/src/plugins/api-class-constructor-plugin.ts diff --git a/packages/ts-docs-gen/examples/simple/docs/api/index.md b/packages/ts-docs-gen/examples/simple/docs/api/index.md index b028f9f1..357e62bb 100644 --- a/packages/ts-docs-gen/examples/simple/docs/api/index.md +++ b/packages/ts-docs-gen/examples/simple/docs/api/index.md @@ -1,22 +1,7 @@ -[ModuleDeclaration-0]: index\foonamespace.md#foonamespace +[ClassDeclaration-0]: index/hello.md#hello # index -## MyFunction() +## interface: Foo -```typescript -function MyFunction(): T -``` - -### Type parameters - -| Name | Constraint type | Default type | -| ---- | -------------------------------------------------------------- | ------------------------- | -| T | \{ myProperty: string; myPropertyTwo?: number \| undefined; \} | \{ myProperty: string; \} | - -### Return type - -T - - -## [FooNamespace][ModuleDeclaration-0] +## [Hello][ClassDeclaration-0] diff --git a/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md b/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md new file mode 100644 index 00000000..55cceef2 --- /dev/null +++ b/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md @@ -0,0 +1,25 @@ +# Hello + +```typescript +class Hello implements Foo +``` +## Constructor + +### constructor(arg) + +This is a constructor + +```typescript +constructor(arg: string) +``` +#### Parameters + +| Name | Type | Description | +| ---- | ------ | ---------------------- | +| arg | string | This is an argument ;) | + + +## Methods + +## class-method: GetFoo + diff --git a/packages/ts-docs-gen/examples/simple/index.ts b/packages/ts-docs-gen/examples/simple/index.ts index e3c82068..76bcd922 100644 --- a/packages/ts-docs-gen/examples/simple/index.ts +++ b/packages/ts-docs-gen/examples/simple/index.ts @@ -211,6 +211,18 @@ // } // } -export class Hello { +export interface Foo { + GetFoo(): TValue; +} + +export class Hello implements Foo { + /** + * This is a constructor + * @param arg This is an argument ;) + */ constructor(arg: string) { } + + GetFoo(): string { + throw new Error("Method not implemented."); + } } diff --git a/packages/ts-docs-gen/src/default-plugins.ts b/packages/ts-docs-gen/src/default-plugins.ts index 17149fbc..a7ca4356 100644 --- a/packages/ts-docs-gen/src/default-plugins.ts +++ b/packages/ts-docs-gen/src/default-plugins.ts @@ -5,6 +5,7 @@ import { ApiFunctionPlugin } from "./plugins/api-function-plugin"; import { ApiTypePlugin } from "./plugins/api-type-plugin"; import { ApiNamespacePlugin } from "./plugins/api-namespace-plugin"; import { ApiClassPlugin } from "./plugins/api-class-plugin"; +import { ApiClassConstructorPlugin } from "./plugins/api-class-constructor-plugin"; export const DefaultPlugins = [ new ApiSourceFilePlugin(), @@ -13,5 +14,6 @@ export const DefaultPlugins = [ new ApiFunctionPlugin(), new ApiTypePlugin(), new ApiNamespacePlugin(), - new ApiClassPlugin() + new ApiClassPlugin(), + new ApiClassConstructorPlugin() ]; diff --git a/packages/ts-docs-gen/src/generator-helpers.ts b/packages/ts-docs-gen/src/generator-helpers.ts index ed2f39fc..0bc2c024 100644 --- a/packages/ts-docs-gen/src/generator-helpers.ts +++ b/packages/ts-docs-gen/src/generator-helpers.ts @@ -356,6 +356,40 @@ export namespace GeneratorHelpers { return `${name}(${parametersString})`; } + export function CallableParametersToSimpleString(text: string, parameters: Contracts.ApiParameterDto[]): string { + const parametersString = parameters + .map(x => x.Name) + .join(", "); + + return `${text}(${parametersString})`; + } + + export function CallableParametersToString( + text: string, + parameters: Contracts.ApiParameterDto[], + returnType?: Contracts.TypeDto + ): string { + // Parameters + let parametersString: string; + if (parameters != null && parameters.length > 0) { + parametersString = parameters + .map(x => `${x.Name}: ${x.Type.Text}`) + .join(", "); + } else { + parametersString = ""; + } + + // ReturnType + let returnTypeString: string; + if (returnType != null) { + returnTypeString = `: ${returnType.Text}`; + } else { + returnTypeString = ""; + } + + return `${text}(${parametersString})${returnTypeString}`; + } + export function GetApiItemsFromReference( items: Contracts.ApiItemReference[], extractedData: ExtractDto diff --git a/packages/ts-docs-gen/src/plugins/api-class-constructor-plugin.ts b/packages/ts-docs-gen/src/plugins/api-class-constructor-plugin.ts new file mode 100644 index 00000000..8d432fe0 --- /dev/null +++ b/packages/ts-docs-gen/src/plugins/api-class-constructor-plugin.ts @@ -0,0 +1,73 @@ +import { Contracts } from "ts-extractor"; +import { MarkdownBuilder, MarkdownGenerator } from "@simplrjs/markdown"; +import { Plugin, SupportedApiItemKindType, PluginOptions, PluginResult, PluginResultData } from "../contracts/plugin"; +import { GeneratorHelpers } from "../generator-helpers"; + +export class ApiClassConstructorPlugin implements Plugin { + public SupportedApiItemKinds(): SupportedApiItemKindType[] { + return [GeneratorHelpers.ApiItemKinds.ClassConstructor]; + } + + public CheckApiItem(item: Contracts.ApiItemDto): boolean { + return true; + } + + private renderParameters(parameters: Contracts.ApiParameterDto[]): PluginResultData { + const pluginResult = GeneratorHelpers.GetDefaultPluginResultData(); + if (parameters.length === 0) { + return pluginResult; + } + + let referenceIds: string[] = []; + const header = ["Name", "Type", "Description"]; + + const content = parameters.map(parameter => { + const parameterTypeDto = GeneratorHelpers.TypeDtoToMarkdownString(parameter.Type); + + referenceIds = referenceIds.concat(parameterTypeDto.References); + + return [parameter.Name, MarkdownGenerator.EscapeString(parameterTypeDto.Text), parameter.Metadata.DocumentationComment]; + }); + + const builder = new MarkdownBuilder() + .Header("Parameters", 4) + .EmptyLine() + .Table(header, content, GeneratorHelpers.DEFAULT_TABLE_OPTIONS) + .EmptyLine(); + + pluginResult.UsedReferences = referenceIds; + pluginResult.Result = builder.GetOutput(); + + return pluginResult; + } + + public Render(options: PluginOptions): PluginResult { + const pluginResult = GeneratorHelpers.GetDefaultPluginResultData(); + const builder = new MarkdownBuilder(); + + // Parameters + const apiParameters = GeneratorHelpers + .GetApiItemsFromReference(options.ApiItem.Parameters, options.ExtractedData); + const parameters = this.renderParameters(apiParameters); + + const heading = GeneratorHelpers.CallableParametersToSimpleString("constructor", apiParameters); + + pluginResult.Headings.push({ ApiItemId: options.Reference.Id, Heading: heading }); + + builder + .Header(heading, 3) + .EmptyLine() + .Text(GeneratorHelpers.RenderApiItemMetadata(options.ApiItem)) + .Code(GeneratorHelpers.CallableParametersToString("constructor", apiParameters), GeneratorHelpers.DEFAULT_CODE_OPTIONS) + .Text(parameters.Result); + + GeneratorHelpers.MergePluginResultData(pluginResult, parameters); + pluginResult.Result = builder.GetOutput(); + + return { + ApiItem: options.ApiItem, + Reference: options.Reference, + ...pluginResult + }; + } +} From 43948e1cafd8b8cd634e9123b5c8c9a6296c4d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20=C5=BDilinskas?= Date: Thu, 28 Dec 2017 16:09:14 +0200 Subject: [PATCH 4/6] Added class method. --- .../examples/simple/docs/api/index.md | 2 - .../examples/simple/docs/api/index/hello.md | 38 ++++++++- packages/ts-docs-gen/examples/simple/index.ts | 10 +-- packages/ts-docs-gen/src/default-plugins.ts | 4 +- packages/ts-docs-gen/src/generator-helpers.ts | 24 +++++- .../src/plugins/api-class-method-plugin.ts | 77 +++++++++++++++++++ 6 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 packages/ts-docs-gen/src/plugins/api-class-method-plugin.ts diff --git a/packages/ts-docs-gen/examples/simple/docs/api/index.md b/packages/ts-docs-gen/examples/simple/docs/api/index.md index 357e62bb..a4736fe9 100644 --- a/packages/ts-docs-gen/examples/simple/docs/api/index.md +++ b/packages/ts-docs-gen/examples/simple/docs/api/index.md @@ -1,7 +1,5 @@ [ClassDeclaration-0]: index/hello.md#hello # index -## interface: Foo - ## [Hello][ClassDeclaration-0] diff --git a/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md b/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md index 55cceef2..19e03345 100644 --- a/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md +++ b/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md @@ -1,7 +1,7 @@ # Hello ```typescript -class Hello implements Foo +class Hello ``` ## Constructor @@ -21,5 +21,39 @@ constructor(arg: string) ## Methods -## class-method: GetFoo +### GetFoo(arg) + +```typescript +public GetFoo(arg: number): string +``` +#### Parameters + +| Name | Type | +| ---- | ------ | +| arg | number | + + +### GetFoo(arg) + +```typescript +public GetFoo(arg: string): string +``` +#### Parameters + +| Name | Type | +| ---- | ------ | +| arg | string | + + +### GetFoo(arg) + +```typescript +public GetFoo(arg: string | number): string +``` +#### Parameters + +| Name | Type | +| ---- | ---------------- | +| arg | string \| number | + diff --git a/packages/ts-docs-gen/examples/simple/index.ts b/packages/ts-docs-gen/examples/simple/index.ts index 76bcd922..11e5b8d3 100644 --- a/packages/ts-docs-gen/examples/simple/index.ts +++ b/packages/ts-docs-gen/examples/simple/index.ts @@ -211,18 +211,16 @@ // } // } -export interface Foo { - GetFoo(): TValue; -} - -export class Hello implements Foo { +export class Hello { /** * This is a constructor * @param arg This is an argument ;) */ constructor(arg: string) { } - GetFoo(): string { + GetFoo(arg: number): string + GetFoo(arg: string): string + GetFoo(arg: string | number): string { throw new Error("Method not implemented."); } } diff --git a/packages/ts-docs-gen/src/default-plugins.ts b/packages/ts-docs-gen/src/default-plugins.ts index a7ca4356..5e1cb196 100644 --- a/packages/ts-docs-gen/src/default-plugins.ts +++ b/packages/ts-docs-gen/src/default-plugins.ts @@ -6,6 +6,7 @@ import { ApiTypePlugin } from "./plugins/api-type-plugin"; import { ApiNamespacePlugin } from "./plugins/api-namespace-plugin"; import { ApiClassPlugin } from "./plugins/api-class-plugin"; import { ApiClassConstructorPlugin } from "./plugins/api-class-constructor-plugin"; +import { ApiClassMethodPlugin } from "./plugins/api-class-method-plugin"; export const DefaultPlugins = [ new ApiSourceFilePlugin(), @@ -15,5 +16,6 @@ export const DefaultPlugins = [ new ApiTypePlugin(), new ApiNamespacePlugin(), new ApiClassPlugin(), - new ApiClassConstructorPlugin() + new ApiClassConstructorPlugin(), + new ApiClassMethodPlugin() ]; diff --git a/packages/ts-docs-gen/src/generator-helpers.ts b/packages/ts-docs-gen/src/generator-helpers.ts index 0bc2c024..3f78715b 100644 --- a/packages/ts-docs-gen/src/generator-helpers.ts +++ b/packages/ts-docs-gen/src/generator-helpers.ts @@ -356,6 +356,22 @@ export namespace GeneratorHelpers { return `${name}(${parametersString})`; } + export function ApiClassMethodToString( + apiItem: Contracts.ApiClassMethodDto, + parameters: Contracts.ApiParameterDto[], + alias?: string + ): string { + const name = alias || apiItem.Name; + + const optional = apiItem.IsOptional ? "?" : ""; + const abstract = apiItem.IsAbstract ? " abstract" : ""; + const async = apiItem.IsAsync ? " async" : ""; + const $static = apiItem.IsStatic ? " static" : ""; + const functionHeader = CallableParametersToString(`${name}${optional}`, parameters, apiItem.ReturnType); + + return `${apiItem.AccessModifier}${$static}${abstract}${async} ${functionHeader}`.trim(); + } + export function CallableParametersToSimpleString(text: string, parameters: Contracts.ApiParameterDto[]): string { const parametersString = parameters .map(x => x.Name) @@ -416,11 +432,11 @@ export namespace GeneratorHelpers { return pathString.split(path.sep).join("/"); } - export function MergePluginResultData(a: T, b: PluginResultData): T { - a.Headings = a.Headings.concat(b.Headings); + export function MergePluginResultData(a: T, b: Partial): T { + a.Headings = a.Headings.concat(b.Headings || []); a.Members = (a.Members || []).concat(b.Members || []); - a.Result = a.Result.concat(b.Result); - a.UsedReferences = a.UsedReferences.concat(b.UsedReferences); + a.Result = a.Result.concat(b.Result || []); + a.UsedReferences = a.UsedReferences.concat(b.UsedReferences || []); return a; } diff --git a/packages/ts-docs-gen/src/plugins/api-class-method-plugin.ts b/packages/ts-docs-gen/src/plugins/api-class-method-plugin.ts new file mode 100644 index 00000000..3f12685b --- /dev/null +++ b/packages/ts-docs-gen/src/plugins/api-class-method-plugin.ts @@ -0,0 +1,77 @@ +import { Contracts } from "ts-extractor"; +import { MarkdownBuilder, MarkdownGenerator } from "@simplrjs/markdown"; +import { Plugin, SupportedApiItemKindType, PluginOptions, PluginResult, PluginResultData } from "../contracts/plugin"; +import { GeneratorHelpers } from "../generator-helpers"; + +export class ApiClassMethodPlugin implements Plugin { + public SupportedApiItemKinds(): SupportedApiItemKindType[] { + return [GeneratorHelpers.ApiItemKinds.ClassMethod]; + } + + public CheckApiItem(item: Contracts.ApiItemDto): boolean { + return true; + } + + private renderParameters(parameters: Contracts.ApiParameterDto[]): PluginResultData { + const pluginResult = GeneratorHelpers.GetDefaultPluginResultData(); + if (parameters.length === 0) { + return pluginResult; + } + + let referenceIds: string[] = []; + const header = ["Name", "Type", "Description"]; + + const content = parameters.map(parameter => { + const parameterTypeDto = GeneratorHelpers.TypeDtoToMarkdownString(parameter.Type); + + referenceIds = referenceIds.concat(parameterTypeDto.References); + + return [parameter.Name, MarkdownGenerator.EscapeString(parameterTypeDto.Text), parameter.Metadata.DocumentationComment]; + }); + + const builder = new MarkdownBuilder() + .Header("Parameters", 4) + .EmptyLine() + .Table(header, content, GeneratorHelpers.DEFAULT_TABLE_OPTIONS) + .EmptyLine(); + + pluginResult.UsedReferences = referenceIds; + pluginResult.Result = builder.GetOutput(); + + return pluginResult; + } + + public Render(options: PluginOptions): PluginResult { + const pluginResult = GeneratorHelpers.GetDefaultPluginResultData(); + const builder = new MarkdownBuilder(); + + // Parameters + const apiParameters = GeneratorHelpers + .GetApiItemsFromReference(options.ApiItem.Parameters, options.ExtractedData); + const parameters = this.renderParameters(apiParameters); + + const heading = GeneratorHelpers.CallableParametersToSimpleString(options.Reference.Alias, apiParameters); + + pluginResult.Headings.push({ ApiItemId: options.Reference.Id, Heading: heading }); + + builder + .Header(heading, 3) + .EmptyLine() + .Text(GeneratorHelpers.RenderApiItemMetadata(options.ApiItem)) + .Code(GeneratorHelpers.ApiClassMethodToString( + options.ApiItem, + apiParameters, + options.Reference.Alias + ), GeneratorHelpers.DEFAULT_CODE_OPTIONS) + .Text(parameters.Result); + + GeneratorHelpers.MergePluginResultData(pluginResult, parameters); + pluginResult.Result = builder.GetOutput(); + + return { + ApiItem: options.ApiItem, + Reference: options.Reference, + ...pluginResult + }; + } +} From 7e7c24d5d4ebf47f58a257a15d5142f1af6ab6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20=C5=BDilinskas?= Date: Thu, 28 Dec 2017 19:30:21 +0200 Subject: [PATCH 5/6] Added ApiClassPropertyPlugin. --- .../examples/simple/docs/api/index/hello.md | 12 +++++ packages/ts-docs-gen/examples/simple/index.ts | 2 + packages/ts-docs-gen/src/default-plugins.ts | 4 +- packages/ts-docs-gen/src/generator-helpers.ts | 10 ++++ .../src/plugins/api-class-property-plugin.ts | 46 +++++++++++++++++++ 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 packages/ts-docs-gen/src/plugins/api-class-property-plugin.ts diff --git a/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md b/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md index 19e03345..cc6438ea 100644 --- a/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md +++ b/packages/ts-docs-gen/examples/simple/docs/api/index/hello.md @@ -57,3 +57,15 @@ public GetFoo(arg: string | number): string | arg | string \| number | +## Properties + +### Foo + +```typescript +public Foo: string; +``` + +### Type + +string + diff --git a/packages/ts-docs-gen/examples/simple/index.ts b/packages/ts-docs-gen/examples/simple/index.ts index 11e5b8d3..724fafda 100644 --- a/packages/ts-docs-gen/examples/simple/index.ts +++ b/packages/ts-docs-gen/examples/simple/index.ts @@ -223,4 +223,6 @@ export class Hello { GetFoo(arg: string | number): string { throw new Error("Method not implemented."); } + + public Foo: string; } diff --git a/packages/ts-docs-gen/src/default-plugins.ts b/packages/ts-docs-gen/src/default-plugins.ts index 5e1cb196..cf90c6a7 100644 --- a/packages/ts-docs-gen/src/default-plugins.ts +++ b/packages/ts-docs-gen/src/default-plugins.ts @@ -7,6 +7,7 @@ import { ApiNamespacePlugin } from "./plugins/api-namespace-plugin"; import { ApiClassPlugin } from "./plugins/api-class-plugin"; import { ApiClassConstructorPlugin } from "./plugins/api-class-constructor-plugin"; import { ApiClassMethodPlugin } from "./plugins/api-class-method-plugin"; +import { ApiClassPropertyPlugin } from "./plugins/api-class-property-plugin"; export const DefaultPlugins = [ new ApiSourceFilePlugin(), @@ -17,5 +18,6 @@ export const DefaultPlugins = [ new ApiNamespacePlugin(), new ApiClassPlugin(), new ApiClassConstructorPlugin(), - new ApiClassMethodPlugin() + new ApiClassMethodPlugin(), + new ApiClassPropertyPlugin() ]; diff --git a/packages/ts-docs-gen/src/generator-helpers.ts b/packages/ts-docs-gen/src/generator-helpers.ts index 3f78715b..8b018276 100644 --- a/packages/ts-docs-gen/src/generator-helpers.ts +++ b/packages/ts-docs-gen/src/generator-helpers.ts @@ -372,6 +372,16 @@ export namespace GeneratorHelpers { return `${apiItem.AccessModifier}${$static}${abstract}${async} ${functionHeader}`.trim(); } + export function ApiClassPropertyToString(apiItem: Contracts.ApiClassPropertyDto, alias?: string): string { + const name = alias || apiItem.Name; + + const optional = apiItem.IsOptional ? "?" : ""; + const abstract = apiItem.IsAbstract ? " abstract" : ""; + const $static = apiItem.IsStatic ? " static" : ""; + + return `${apiItem.AccessModifier}${$static}${abstract} ${name}${optional}: ${apiItem.Type.Text};`; + } + export function CallableParametersToSimpleString(text: string, parameters: Contracts.ApiParameterDto[]): string { const parametersString = parameters .map(x => x.Name) diff --git a/packages/ts-docs-gen/src/plugins/api-class-property-plugin.ts b/packages/ts-docs-gen/src/plugins/api-class-property-plugin.ts new file mode 100644 index 00000000..1df3b160 --- /dev/null +++ b/packages/ts-docs-gen/src/plugins/api-class-property-plugin.ts @@ -0,0 +1,46 @@ +import { Contracts } from "ts-extractor"; +import { MarkdownBuilder } from "@simplrjs/markdown"; +import { Plugin, SupportedApiItemKindType, PluginOptions, PluginResult } from "../contracts/plugin"; +import { GeneratorHelpers } from "../generator-helpers"; + +export class ApiClassPropertyPlugin implements Plugin { + public SupportedApiItemKinds(): SupportedApiItemKindType[] { + return [GeneratorHelpers.ApiItemKinds.ClassProperty]; + } + + public CheckApiItem(item: Contracts.ApiItemDto): boolean { + return true; + } + + public Render(options: PluginOptions): PluginResult { + const pluginResultData = GeneratorHelpers.GetDefaultPluginResultData(); + const builder = new MarkdownBuilder(); + + const heading = options.Reference.Alias; + pluginResultData.Headings.push({ ApiItemId: options.Reference.Id, Heading: heading }); + + const typeStringDto = GeneratorHelpers.TypeDtoToMarkdownString(options.ApiItem.Type); + pluginResultData.UsedReferences = pluginResultData.UsedReferences.concat(typeStringDto.References); + + builder + .Header(heading, 3) + .EmptyLine() + .Text(GeneratorHelpers.RenderApiItemMetadata(options.ApiItem)) + .Code(GeneratorHelpers.ApiClassPropertyToString( + options.ApiItem, + options.Reference.Alias + ), GeneratorHelpers.DEFAULT_CODE_OPTIONS) + .EmptyLine() + .Header("Type", 3) + .EmptyLine() + .Text(typeStringDto.Text); + + pluginResultData.Result = builder.GetOutput(); + + return { + ApiItem: options.ApiItem, + Reference: options.Reference, + ...pluginResultData + }; + } +} From b03f5795d122b141e9e82c70f0de11ebd218c117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20=C5=BDilinskas?= Date: Fri, 29 Dec 2017 13:14:46 +0200 Subject: [PATCH 6/6] Updated snapshots. --- .../simple-project-1.test.ts.snap | 42 +++++++++++++---- .../simple-project-2.test.ts.snap | 46 +++++++++++++++++-- 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/packages/ts-docs-gen/tests/cases/__tests__/__snapshots__/simple-project-1.test.ts.snap b/packages/ts-docs-gen/tests/cases/__tests__/__snapshots__/simple-project-1.test.ts.snap index 53bab2b8..3af0b655 100644 --- a/packages/ts-docs-gen/tests/cases/__tests__/__snapshots__/simple-project-1.test.ts.snap +++ b/packages/ts-docs-gen/tests/cases/__tests__/__snapshots__/simple-project-1.test.ts.snap @@ -5,11 +5,11 @@ Array [ Object { "FileLocation": "index.md", "Result": Array [ - "[ClassDeclaration-0]: index/foo.md#class-foo", - "[ClassDeclaration-1]: index/world.md#class-world", - "[ClassDeclaration-2]: index/earth.md#class-earth", - "[ClassDeclaration-2]: index/earth.md#class-earth", - "[ClassDeclaration-1]: index/world.md#class-world", + "[ClassDeclaration-0]: index/foo.md#foo", + "[ClassDeclaration-1]: index/world.md#world", + "[ClassDeclaration-2]: index/earth.md#earth", + "[ClassDeclaration-2]: index/earth.md#earth", + "[ClassDeclaration-1]: index/world.md#world", "# index", "", "## EnumList", @@ -364,21 +364,47 @@ Array [ Object { "FileLocation": "index/foo.md", "Result": Array [ - "## class: Foo", + "# Foo", + "", + "\`\`\`typescript", + "class Foo", + "\`\`\`", + "## Methods", + "", + "### HandleMessage(message)", + "", + "\`\`\`typescript", + "public HandleMessage(message: string): string", + "\`\`\`", + "#### Parameters", + "", + "| Name | Type |", + "| ------- | ------ |", + "| message | string |", + "", + "", "", ], }, Object { "FileLocation": "index/world.md", "Result": Array [ - "## class: World", + "# World", + "", + "\`\`\`typescript", + "class World", + "\`\`\`", "", ], }, Object { "FileLocation": "index/earth.md", "Result": Array [ - "## class: Earth", + "# Earth", + "", + "\`\`\`typescript", + "class Earth", + "\`\`\`", "", ], }, diff --git a/packages/ts-docs-gen/tests/cases/__tests__/__snapshots__/simple-project-2.test.ts.snap b/packages/ts-docs-gen/tests/cases/__tests__/__snapshots__/simple-project-2.test.ts.snap index 64b34875..8897f5c1 100644 --- a/packages/ts-docs-gen/tests/cases/__tests__/__snapshots__/simple-project-2.test.ts.snap +++ b/packages/ts-docs-gen/tests/cases/__tests__/__snapshots__/simple-project-2.test.ts.snap @@ -5,8 +5,8 @@ Array [ Object { "FileLocation": "index.md", "Result": Array [ - "[ClassDeclaration-0]: index/foo.md#class-foo", - "[ClassDeclaration-1]: index/foostart.md#class-foostart", + "[ClassDeclaration-0]: index/foo.md#foo", + "[ClassDeclaration-1]: index/foostart.md#foostart", "# index", "", "## [Foo][ClassDeclaration-0]", @@ -19,21 +19,57 @@ Array [ Object { "FileLocation": "index/foo.md", "Result": Array [ - "## class: Foo", + "# Foo", + "", + "\`\`\`typescript", + "class Foo", + "\`\`\`", + "## Methods", + "", + "### GetMessage(message)", + "", + "\`\`\`typescript", + "public GetMessage(message: string): string", + "\`\`\`", + "#### Parameters", + "", + "| Name | Type |", + "| ------- | ------ |", + "| message | string |", + "", + "", "", ], }, Object { "FileLocation": "index/foostart.md", "Result": Array [ - "## class: FooStart", + "# FooStart", + "", + "\`\`\`typescript", + "class FooStart", + "\`\`\`", + "## Methods", + "", + "### HandleMessage(message)", + "", + "\`\`\`typescript", + "public HandleMessage(message: string): string", + "\`\`\`", + "#### Parameters", + "", + "| Name | Type |", + "| ------- | ------ |", + "| message | string |", + "", + "", "", ], }, Object { "FileLocation": "foo.md", "Result": Array [ - "[ClassDeclaration-0]: index/foo.md#class-foo", + "[ClassDeclaration-0]: index/foo.md#foo", "# foo", "", "## [Foo][ClassDeclaration-0]",