diff --git a/.gitignore b/.gitignore index 4f108f96..ccdfc1e3 100644 --- a/.gitignore +++ b/.gitignore @@ -292,5 +292,5 @@ coverage package-deps.json # Tests -*/__tests__/* -!*/__tests__/**/__snapshots__ +**/tests/cases/__tests__/*.test.ts + diff --git a/common/config/rush/npm-shrinkwrap.json b/common/config/rush/npm-shrinkwrap.json index 285b9fda..e5fe5a84 100644 --- a/common/config/rush/npm-shrinkwrap.json +++ b/common/config/rush/npm-shrinkwrap.json @@ -6,9 +6,9 @@ "dependencies": { "@rush-temp/test-generator-cli": { "version": "file:projects/test-generator-cli.tgz", - "integrity": "sha1-7hRxKrHs2nw/Tg3difiN7wlLcpI=", + "integrity": "sha1-poL86JfifvnYdj6kO8BwW/R5VEA=", "requires": { - "@types/fs-extra": "4.0.6", + "@types/fs-extra": "4.0.7", "@types/handlebars": "4.0.36", "@types/yargs": "10.0.0", "fast-glob": "1.0.1", @@ -23,12 +23,12 @@ }, "@rush-temp/ts-docs-gen": { "version": "file:projects/ts-docs-gen.tgz", - "integrity": "sha1-q5PE2Czi6RYJoEbNl8S7rSkODP4=", + "integrity": "sha1-IIM5lH+f0v1NDXEIhk/erutcOrQ=", "requires": { - "@simplrjs/markdown": "1.0.1", - "@types/fs-extra": "4.0.6", - "@types/jest": "21.1.8", - "@types/sinon": "4.1.1", + "@simplrjs/markdown": "1.0.3", + "@types/fs-extra": "4.0.7", + "@types/jest": "21.1.9", + "@types/sinon": "4.1.2", "fast-glob": "1.0.1", "fs-extra": "4.0.3", "jest": "21.2.1", @@ -42,20 +42,20 @@ } }, "@simplrjs/markdown": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@simplrjs/markdown/-/markdown-1.0.1.tgz", - "integrity": "sha512-5cRr5I/CVRwo8bLJOmui8Jf9iwXgVcr81+9rO93IyLutm5GBrkSA8ZSwzovVuWlgA36sml9Dklrl1xP4GQEurA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@simplrjs/markdown/-/markdown-1.0.3.tgz", + "integrity": "sha512-QkC79ttUek7d9w1yysaETZnsD7WO7JOLCbAIX8kCAeZhMY/21ZRULWjb3Pl7SBm6QqqYTOnKl8rvikmbVaGtLA==", "requires": { "@types/string": "0.0.29", "string": "3.3.3" } }, "@types/fs-extra": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.6.tgz", - "integrity": "sha512-SVQDcOe1t7qSRzJFjkMx4V/0hc3TcGX/f51Dxx3Q/rpeg7nvFiort6QJTpJATOZH/YqhzJ1xt0qjvotxOJiCkQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.7.tgz", + "integrity": "sha512-BN48b/2F3kL0Ual7tjcHjj0Fl+nuYKtHa0G/xT3Q43HuCpN7rQD5vIx6Aqnl9x10oBI5xMJh8Ly+FQpP205JlA==", "requires": { - "@types/node": "8.0.58" + "@types/node": "8.5.2" } }, "@types/handlebars": { @@ -64,19 +64,19 @@ "integrity": "sha512-LjNiTX7TY7wtuC6y3QwC93hKMuqYhgV9A1uXBKNvZtVC8ZvyWAjZkJ5BvT0K7RKqORRYRLMrqCxpw5RgS+MdrQ==" }, "@types/jest": { - "version": "21.1.8", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-21.1.8.tgz", - "integrity": "sha512-hQbL8aBM/g5S++sM1gb4yC73Dg+FK3uYE+Ioht1RPy629+LV/RmH6q+e+jbQEwKJdWAP/YE4s67CPO+ElkMivg==" + "version": "21.1.9", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-21.1.9.tgz", + "integrity": "sha512-81wGgp3KLAhcrDQBeGADeuH1SvOmgZty5XF/mdPBOSxjEgAT9rcLr4CQCk2cRRjZE8vzmx7S1SPL6D/Z8OOR6A==" }, "@types/node": { - "version": "8.0.58", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.58.tgz", - "integrity": "sha512-V746iUU7eHNdzQipoACuguDlVhC7IHK8CES1jSkuFt352wwA84BCWPXaGekBd7R5XdNK5ReHONDVKxlL9IreAw==" + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.2.tgz", + "integrity": "sha512-KA4GKOpgXnrqEH2eCVhiv2CsxgXGQJgV1X0vsGlh+WCnxbeAE1GT44ZsTU1IN5dEeV/gDupKa7gWo08V5IxWVQ==" }, "@types/sinon": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-4.1.1.tgz", - "integrity": "sha512-4TaA0fxqXNhx8ph+cylpN/hBrkxru0LviHlfZU6Yljl6ztUL7enUFnJ3XMYruSsyycnZgfGqOiw1kiynKlXLNw==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-4.1.2.tgz", + "integrity": "sha512-fL6bJHYRzbw/7ofbKiJ65SOAasoe5mZhHNSYKxWsF3sGl/arhRwDPwXJqM1xofKNTQD14HNX9VruicM7pm++mQ==" }, "@types/string": { "version": "0.0.29", @@ -107,9 +107,9 @@ } }, "ajv": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz", - "integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { "co": "4.6.0", "fast-deep-equal": "1.0.0", @@ -299,6 +299,11 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -1525,7 +1530,7 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "requires": { - "ajv": "5.5.1", + "ajv": "5.5.2", "har-schema": "2.0.0" } }, @@ -4024,14 +4029,15 @@ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "requires": { - "extend-shallow": "3.0.1" + "extend-shallow": "3.0.2" }, "dependencies": { "extend-shallow": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.1.tgz", - "integrity": "sha512-Fg1xXAv+qXKdwHiJFMcZSqsMcbPlkzsZtf8KkLJ2fqnP+lqg2RjEKgDcSfO9CO1+p4LZKgApDBUUUqKaaRhwZQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "requires": { + "assign-symbols": "1.0.0", "is-extendable": "1.0.1" } }, @@ -4411,7 +4417,7 @@ "resolved": "https://registry.npmjs.org/ts-extractor/-/ts-extractor-2.0.0.tgz", "integrity": "sha512-snSSnVkhc/jDo0ppJa8t3/aIbMcI3qg6HsB/iC0UdG+5KzAKHGQBuM5QwaFng6O7KKbk/Ljb8RgwN5uwd1DYHA==", "requires": { - "@types/fs-extra": "4.0.6", + "@types/fs-extra": "4.0.7", "fs-extra": "4.0.3", "read-package-json": "2.0.12", "simplr-logger": "1.0.1", @@ -4470,13 +4476,13 @@ "resolve": "1.5.0", "semver": "5.4.1", "tslib": "1.8.1", - "tsutils": "2.13.0" + "tsutils": "2.13.1" } }, "tsutils": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.0.tgz", - "integrity": "sha512-FuWzNJbMsp3gcZMbI3b5DomhW4Ia41vMxjN63nKWI0t7f+I3UmHfRl0TrXJTwI2LUduDG+eR1Mksp3pvtlyCFQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.1.tgz", + "integrity": "sha512-XMOEvc2TiYesVSOJMI7OYPnBMSgcvERuGW5Li/J+2A0TuH607BPQnOLQ82oSPZCssB8c9+QGi6qhTBa/f1xQRA==", "requires": { "tslib": "1.8.1" } @@ -4793,13 +4799,13 @@ "string-width": "2.1.1", "which-module": "2.0.0", "y18n": "3.2.1", - "yargs-parser": "8.0.0" + "yargs-parser": "8.1.0" } }, "yargs-parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.0.0.tgz", - "integrity": "sha1-IdR2Mw5agieaS4gTRb8GYQLiGcY=", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", "requires": { "camelcase": "4.1.0" } diff --git a/packages/ts-docs-gen/examples/simple/docs/api/exported-functions.md b/packages/ts-docs-gen/examples/simple/docs/api/exported-functions.md index 9f5ee535..848a1922 100644 --- a/packages/ts-docs-gen/examples/simple/docs/api/exported-functions.md +++ b/packages/ts-docs-gen/examples/simple/docs/api/exported-functions.md @@ -1,3 +1,21 @@ -## function: Foo +## Foo() + +```typescript +function Foo(): string +``` + +### Return type + +string + + +## Bar() + +```typescript +function Bar(): string +``` + +### Return type + +string -## function: Bar 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 781e8fb2..af7b4273 100644 --- a/packages/ts-docs-gen/examples/simple/docs/api/index.md +++ b/packages/ts-docs-gen/examples/simple/docs/api/index.md @@ -1,130 +1,16 @@ -[EnumDeclaration-0]: index.md#uogos -[ModuleDeclaration-1]: index\boonamespace.md#boonamespace -## class: World - -## Uogos - -Warning: Beta! - -Deprecated! - -Some information -2nd line of some information -3rd line of some information -4th line of some information -5th line of some information - -> Some summary about this package version. - - -```typescript -enum Uogos { - Jokie = "jokie", - Braskes = "braskes" -} -``` - -| Name | Value | -| ------- | --------- | -| Jokie | "jokie" | -| Braskes | "braskes" | - -## Skaiciai - - -```typescript -enum Skaiciai { - Nulis = 0, - Vienas = 1, - Du = 2 -} -``` - -| Name | Value | -| ------ | ----- | -| Nulis | 0 | -| Vienas | 1 | -| Du | 2 | - -## Sarasas - - -```typescript -enum Sarasas { - Pirmas = 0, - Antras = 1, - Trecias = 2 -} -``` - -| Name | Value | Description | -| ------- | ----- | --------------------- | -| Pirmas | 0 | Pirmo description'as | -| Antras | 1 | Antro description'as | -| Trecias | 2 | Trečio description'as | - -## ConstSkaiciai - - -```typescript -enum ConstSkaiciai { - PirmasC = 0, - AntrasC = 1, - TreciasC = 2 -} -``` - -| Name | Value | -| -------- | ----- | -| PirmasC | 0 | -| AntrasC | 1 | -| TreciasC | 2 | - -## ConstSarasas - - -```typescript -enum ConstSarasas { - PirmasC = 0, - AntrasC = 1, - TreciasC = 2 -} -``` - -| Name | Value | Description | -| -------- | ----- | --------------------- | -| PirmasC | 0 | Pirmo description'as | -| AntrasC | 1 | Antro description'as | -| TreciasC | 2 | Trečio description'as | - -## ConstUogos - - -```typescript -enum ConstUogos { - Jokie = "jokie", - Braskes = "braskes" -} -``` - -| Name | Value | -| ------- | --------- | -| Jokie | "jokie" | -| Braskes | "braskes" | - -## Hello - -Deprecated: Use uogos instead ;)! +## MyFunction() ```typescript -type Hello = Uogos; +function MyFunction(): T ``` -### Type +### Type parameters -[Uogos][EnumDeclaration-0] +| Name | Constraint type | Default type | +| ---- | -------------------------------------------------------------- | ------------------------- | +| T | \{ myProperty: string; myPropertyTwo?: number \| undefined; \} | \{ myProperty: string; \} | -# FooNamespace +### Return type -## [BooNamespace][ModuleDeclaration-1] +T diff --git a/packages/ts-docs-gen/examples/simple/index.ts b/packages/ts-docs-gen/examples/simple/index.ts index 49451dc1..0e7421ba 100644 --- a/packages/ts-docs-gen/examples/simple/index.ts +++ b/packages/ts-docs-gen/examples/simple/index.ts @@ -2,21 +2,59 @@ // import { Foo } from "./exported-functions"; -export class World { } +// export class World { } +// export class Earth { } // export class Earth { } // export declare const Hello: World & Earth; // export const FooFunc = Foo; +//--------------------------------------------------------- + + +// #region Parameters + +// #endregion Parameters + // export function Foo(): string { // return "foo"; // } -// export function Bar(): string { +// /** +// * Some general comment about Bar function. +// * +// * @beta Some comment on beta. +// * @deprecated +// */ +// export function Bar(parameter1: string, parameter2: number): string { // return "bar"; // } +// #region Return types +// export function FunctionWithoutReturnType>(parameter1: string, parameter2: Promise) { +// return "bar"; +// } + +// export function FunctionWithGenericReturnType(): Array { +// return []; +// } + +// export function FunctionWithPrimitiveReturnType(): boolean { +// return true; +// } + +// export function FunctionWithUnionReturnType(): "something" | "nothing" { +// return "nothing"; +// } + +// export function FunctionWithIntersectionReturnType(): Earth & World { +// return {}; +// } +// #endregion Return types + +// ------------------------------------------------------ + // export * from "./exported-functions"; // export { Kintamasis as Pakeistas } from "./exported-const-variables"; // export type A = number & { ok(): TValue }; @@ -41,11 +79,11 @@ export class World { } // anotherProperty: number; // } -// export function Funkcija(): T { -// return { -// myProperty: "asd" -// } as T; -// } +export function MyFunction(): T { + return { + myProperty: "sampleString" + } as T; +} // export interface MyInterface { // (param1: TValue, param2: TValue): boolean; @@ -71,68 +109,63 @@ export class World { } // export const name = "some-kind-of-module"; // } -/** - * Some information - * 2nd line of some information - * 3rd line of some information - * 4th line of some information - * 5th line of some information - * @summary Some summary about this package version. - * @summary 2nd of some summary about this package version. - * @deprecated - * @beta - */ -export enum Uogos { - Jokie = "jokie", - Braskes = "braskes" -} - -export enum Skaiciai { - Nulis = 0, - Vienas = 1, - Du = 2 -} +// /** +// * Some information +// * 2nd line of some information +// * 3rd line of some information +// * 4th line of some information +// * 5th line of some information +// * @summary Some summary about this package version. +// * @summary 2nd of some summary about this package version. +// * @deprecated +// * @beta +// */ +// export enum Uogos { +// Jokie = "jokie", +// Braskes = "braskes" +// } -export enum Sarasas { - /** - * Pirmo description'as - */ - Pirmas, - /** - * Antro description'as - */ - Antras, - /** - * Trečio description'as - */ - Trecias -} +// export enum Skaiciai { +// Nulis = 0, +// Vienas = 1, +// Du = 2 +// } -export const enum ConstSkaiciai { - PirmasC = 0, - AntrasC = 1, - TreciasC = 2 -} +// export enum Sarasas { +// /** +// * Pirmo description'as +// */ +// Pirmas, +// /** +// * Antro description'as +// */ +// Antras, +// /** +// * Trečio description'as +// */ +// Trecias +// } -export const enum ConstSarasas { - /** - * Pirmo description'as - */ - PirmasC, - /** - * Antro description'as - */ - AntrasC, - /** - * Trečio description'as - */ - TreciasC -} +// export const enum ConstSkaiciai { +// PirmasC = 0, +// AntrasC = 1, +// TreciasC = 2 +// } -export const enum ConstUogos { - Jokie = "jokie", - Braskes = "braskes" -} +// export const enum ConstSarasas { +// /** +// * Pirmo description'as +// */ +// PirmasC, +// /** +// * Antro description'as +// */ +// AntrasC, +// /** +// * Trečio description'as +// */ +// TreciasC +// } // export interface Boo { // Boos: string[]; @@ -144,10 +177,6 @@ export const enum ConstUogos { // Type: TType; // } -// export async function GetFoo(): Promise { -// return; -// } - // export interface Bar extends Foo, Boo { // OtherStuff: string[]; // } @@ -169,15 +198,15 @@ export const enum ConstUogos { // public abstract Bar(): string; // } -/** - * @deprecated Use uogos instead ;) - */ -export type Hello = Uogos; +// /** +// * @deprecated Use uogos instead ;) +// */ +// export type Hello = Uogos; -export namespace FooNamespace { - export namespace BooNamespace { - export namespace BooNamespace2 { - export const Hello = "World!"; - } - } -} +// export namespace FooNamespace { +// export namespace BooNamespace { +// export namespace BooNamespace2 { +// export const Hello = "World!"; +// } +// } +// } diff --git a/packages/ts-docs-gen/package.json b/packages/ts-docs-gen/package.json index 0647a35c..32048ed8 100644 --- a/packages/ts-docs-gen/package.json +++ b/packages/ts-docs-gen/package.json @@ -15,7 +15,7 @@ "engine": "node >= 7.5.0", "author": "simplrjs (https://github.com/simplrjs)", "dependencies": { - "@simplrjs/markdown": "^1.0.1", + "@simplrjs/markdown": "^1.0.3", "@types/fs-extra": "^4.0.5", "fast-glob": "^1.0.1", "fs-extra": "^4.0.3", diff --git a/packages/ts-docs-gen/src/default-plugins.ts b/packages/ts-docs-gen/src/default-plugins.ts index d7761689..38f555a7 100644 --- a/packages/ts-docs-gen/src/default-plugins.ts +++ b/packages/ts-docs-gen/src/default-plugins.ts @@ -1,11 +1,13 @@ import { ApiVariablePlugin } from "./plugins/api-variable-plugin"; 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"; export const DefaultPlugins = [ new ApiVariablePlugin(), new ApiEnumPlugin(), + new ApiFunctionPlugin(), new ApiTypePlugin(), new ApiNamespacePlugin() ]; diff --git a/packages/ts-docs-gen/src/file-manager.ts b/packages/ts-docs-gen/src/file-manager.ts index e36df055..fce83990 100644 --- a/packages/ts-docs-gen/src/file-manager.ts +++ b/packages/ts-docs-gen/src/file-manager.ts @@ -55,13 +55,21 @@ export class FileManager implements FileManagerInterface { // Link definitions to file location. const linkDefinitions: string[] = []; for (const item of items) { + item.UsedReferences .forEach(referenceId => { const filePath = path.dirname(fileLocation); - const resolvePath = path.relative(filePath, this.referenceToFile.get(referenceId) || "#__error"); + + const referenceString = this.referenceToFile.get(referenceId); + const resolvePath = path.relative(filePath, referenceString || "#__error"); + linkDefinitions.push( MarkdownGenerator.LinkDefinition(referenceId, resolvePath) ); + + if (!referenceString) { + console.warn(`Reference "${referenceId}" not found. Check ${fileLocation}.`); + } }); } diff --git a/packages/ts-docs-gen/src/generator-helpers.ts b/packages/ts-docs-gen/src/generator-helpers.ts index 041d6dab..9026d5cf 100644 --- a/packages/ts-docs-gen/src/generator-helpers.ts +++ b/packages/ts-docs-gen/src/generator-helpers.ts @@ -1,9 +1,17 @@ +import * as ts from "typescript"; import { Contracts, ExtractDto } from "ts-extractor"; -import { MarkdownGenerator, MarkdownBuilder } from "@simplrjs/markdown"; +import { MarkdownGenerator, MarkdownBuilder, Contracts as MarkdownContracts } from "@simplrjs/markdown"; import { ApiItemReference } from "./contracts/api-item-reference"; import { ApiItemKindsAdditional } from "./contracts/plugin"; export namespace GeneratorHelpers { + export type TypeToStringDto = ReferenceDto; + + export interface ReferenceDto { + References: string[]; + Text: T; + } + export const MARKDOWN_EXT = ".md"; export const ApiItemKinds: typeof ApiItemKindsAdditional & typeof Contracts.ApiItemKinds = @@ -13,11 +21,12 @@ export namespace GeneratorHelpers { return Object.assign(Contracts.ApiItemKinds, ApiItemKindsAdditional); } - export interface TypeToStringDto { - References: string[]; - Text: string; + // TODO: reexport InternalSymbolName in ts-extractor. + export function IsTypeScriptInternalSymbolName(name: string): boolean { + return Object.values(ts.InternalSymbolName).indexOf(name) !== -1; } + // TODO: implement type literal and function type. export function TypeDtoToMarkdownString(type: Contracts.TypeDto): TypeToStringDto { let references: string[] = []; let text: string = ""; @@ -57,11 +66,16 @@ export namespace GeneratorHelpers { } // Basic type with reference. - if (type.ReferenceId != null) { - text = MarkdownGenerator.Link(type.Name || type.Text, type.ReferenceId, true); - references.push(type.ReferenceId); + if (type.Name == null || IsTypeScriptInternalSymbolName(type.Name)) { + text = type.Text; } else { - text = type.Name || type.Text; + // FIXME: do not use flag string. Exclude Type parameters references. + if (type.ReferenceId != null && type.FlagsString !== "TypeParameter") { + text = MarkdownGenerator.Link(type.Name || type.Text, type.ReferenceId, true); + references.push(type.ReferenceId); + } else { + text = type.Name; + } } } } @@ -203,6 +217,10 @@ export namespace GeneratorHelpers { lang: "typescript" }; + export const DEFAULT_TABLE_OPTIONS: MarkdownContracts.TableOptions = { + removeColumnIfEmpty: true + }; + export function FixSentence(sentence: string, punctuationMark: string = "."): string { const trimmedSentence = sentence.trim(); const punctuationMarks = ".!:;,-"; @@ -221,4 +239,80 @@ export namespace GeneratorHelpers { return `type ${name} = ${item.Type.Text};`; } + + /** + * From ApiFunction to build function head. + * + * Return example: `function foo(arg: TValue): void` + */ + export function ApiFunctionToString( + apiItem: Contracts.ApiFunctionDto, + typeParameters?: Contracts.ApiTypeParameterDto[], + parameters?: Contracts.ApiParameterDto[], + alias?: string + ): string { + const name = alias || apiItem.Name; + + // TypeParameters + let typeParametersString: string; + if (typeParameters != null && typeParameters.length > 0) { + const params: string[] = typeParameters.map(TypeParameterToString); + typeParametersString = `<${params.join(", ")}>`; + } else { + typeParametersString = ""; + } + + // Parameters + let parametersString: string; + if (parameters != null && parameters.length > 0) { + parametersString = parameters + .map(x => `${x.Name}: ${x.Type.Text}`) + .join(", "); + } else { + parametersString = ""; + } + + // ReturnType + const returnType = apiItem.ReturnType != null ? `: ${apiItem.ReturnType.Text}` : ""; + + return `function ${name}${typeParametersString}(${parametersString})${returnType}`; + } + + export function TypeParameterToString(apiItem: Contracts.ApiTypeParameterDto): string { + const $extends = apiItem.ConstraintType != null ? ` extends ${apiItem.ConstraintType.Text}` : ""; + const defaultType = apiItem.DefaultType != null ? ` = ${apiItem.DefaultType.Text}` : ""; + + return `${apiItem.Name}${$extends}${defaultType}`; + } + + export function ApiFunctionToSimpleString( + alias: string, + apiItem: Contracts.ApiFunctionDto, + parametersApiItems: Contracts.ApiParameterDto[] + ): string { + const name = alias || apiItem.Name; + const parametersString = parametersApiItems + .map(x => x.Name) + .join(", "); + + return `${name}(${parametersString})`; + } + + export function GetApiItemsFromReferenceTuple( + items: Contracts.ApiItemReferenceTuple, + extractedData: ExtractDto + ): T[] { + const apiItems: T[] = []; + + for (const itemReferences of items) { + const [, references] = itemReferences; + + for (const reference of references) { + const apiItem = extractedData.Registry[reference] as T; + apiItems.push(apiItem); + } + } + + return apiItems; + } } diff --git a/packages/ts-docs-gen/src/plugins/api-enum-plugin.ts b/packages/ts-docs-gen/src/plugins/api-enum-plugin.ts index 7debeea3..481d6234 100644 --- a/packages/ts-docs-gen/src/plugins/api-enum-plugin.ts +++ b/packages/ts-docs-gen/src/plugins/api-enum-plugin.ts @@ -1,10 +1,11 @@ -import { Contracts, ExtractDto } from "ts-extractor"; +import { Contracts } from "ts-extractor"; import { MarkdownGenerator, MarkdownBuilder } from "@simplrjs/markdown"; import { GeneratorHelpers } from "../generator-helpers"; import { Plugin, SupportedApiItemKindType, PluginResult, PluginOptions, PluginHeading } from "../contracts/plugin"; // TODO: const enums implementation. + export class ApiEnumPlugin implements Plugin { public SupportedApiItemKinds(): SupportedApiItemKindType[] { return [GeneratorHelpers.ApiItemKinds.Enum]; @@ -22,23 +23,6 @@ export class ApiEnumPlugin implements Plugin { return MarkdownGenerator.Table(header, content, { removeColumnIfEmpty: true }); } - /** - * Resolve api items of an enum from ApiItemReferenceTuple. - */ - private getEnumMembers(members: Contracts.ApiItemReferenceTuple, extractedData: ExtractDto): Contracts.ApiEnumMemberDto[] { - const apiItems: Contracts.ApiEnumMemberDto[] = []; - - for (const memberReferences of members) { - const [, references] = memberReferences; - for (const reference of references) { - const apiItem = extractedData.Registry[reference] as Contracts.ApiEnumMemberDto; - apiItems.push(apiItem); - } - } - - return apiItems; - } - public Render(data: PluginOptions): PluginResult { const heading: string = data.Reference.Alias; const headings: PluginHeading[] = [ @@ -48,7 +32,10 @@ export class ApiEnumPlugin implements Plugin { } ]; - const enumMembers = this.getEnumMembers(data.ApiItem.Members, data.ExtractedData); + const enumMembers = GeneratorHelpers.GetApiItemsFromReferenceTuple( + data.ApiItem.Members, + data.ExtractedData + ); const builder = new MarkdownBuilder() .Header(heading, 2) .EmptyLine() diff --git a/packages/ts-docs-gen/src/plugins/api-function-plugin.ts b/packages/ts-docs-gen/src/plugins/api-function-plugin.ts new file mode 100644 index 00000000..1ce9adfd --- /dev/null +++ b/packages/ts-docs-gen/src/plugins/api-function-plugin.ts @@ -0,0 +1,170 @@ +import { Contracts } from "ts-extractor"; +import { MarkdownBuilder, MarkdownGenerator } from "@simplrjs/markdown"; + +import { GeneratorHelpers } from "../generator-helpers"; +import { SupportedApiItemKindType, Plugin, PluginResult, PluginOptions, PluginHeading } from "../contracts/plugin"; +import { ApiFunctionDto } from "ts-extractor/dist/contracts"; + +export class ApiFunctionPlugin implements Plugin { + public SupportedApiItemKinds(): SupportedApiItemKindType[] { + return [GeneratorHelpers.ApiItemKinds.Function]; + } + + public CheckApiItem(item: ApiFunctionDto): boolean { + return true; + } + + // TODO: add description from @param jsdoc tag. + private resolveFunctionParameters(parameters: Contracts.ApiParameterDto[]): GeneratorHelpers.ReferenceDto { + if (parameters.length === 0) { + return { + References: [], + Text: [] + }; + } + + 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)]; + }); + + const text = new MarkdownBuilder() + .Header("Parameters", 3) + .EmptyLine() + .Table(header, content, GeneratorHelpers.DEFAULT_TABLE_OPTIONS) + .EmptyLine() + .GetOutput(); + + return { + Text: text, + References: referenceIds + }; + } + + // TODO: add description from @template jsdoc tag. + private resolveFunctionTypeParameters(typeParameters: Contracts.ApiTypeParameterDto[]): GeneratorHelpers.ReferenceDto { + let referenceIds: string[] = []; + + if (typeParameters.length === 0) { + return { + References: [], + Text: [] + }; + } + + const header = ["Name", "Constraint type", "Default type"]; + const content = typeParameters.map(typeParameter => { + let constraintType: string = ""; + let defaultType: string = ""; + + if (typeParameter.ConstraintType) { + const parsedConstraintType = GeneratorHelpers.TypeDtoToMarkdownString(typeParameter.ConstraintType); + + referenceIds = referenceIds.concat(parsedConstraintType.References); + constraintType = MarkdownGenerator.EscapeString(parsedConstraintType.Text); + } + + if (typeParameter.DefaultType) { + const parsedDefaultType = GeneratorHelpers.TypeDtoToMarkdownString(typeParameter.DefaultType); + + referenceIds = referenceIds.concat(parsedDefaultType.References); + defaultType = MarkdownGenerator.EscapeString(parsedDefaultType.Text); + } + + return [typeParameter.Name, constraintType, defaultType]; + }); + + const text = new MarkdownBuilder() + .Header("Type parameters", 3) + .EmptyLine() + .Table(header, content, GeneratorHelpers.DEFAULT_TABLE_OPTIONS) + .EmptyLine() + .GetOutput(); + + return { + References: referenceIds, + Text: text + }; + } + + private resolveReturnType(typeDto?: Contracts.TypeDto): GeneratorHelpers.ReferenceDto { + if (typeDto == null) { + return { + References: [], + Text: [] + }; + } + + const parsedReturnType = GeneratorHelpers.TypeDtoToMarkdownString(typeDto); + + const text = new MarkdownBuilder() + .Header("Return type", 3) + .EmptyLine() + .Text(parsedReturnType.Text) + .EmptyLine() + .GetOutput(); + + return { + Text: text, + References: parsedReturnType.References + }; + } + + public Render(data: PluginOptions): PluginResult { + const alias = data.Reference.Alias; + + const headings: PluginHeading[] = [ + { + ApiItemId: data.Reference.Id, + Heading: alias + } + ]; + + const parameters = GeneratorHelpers.GetApiItemsFromReferenceTuple( + data.ApiItem.Parameters, + data.ExtractedData + ); + const resolvedParametersDto = this.resolveFunctionParameters(parameters); + + const typeParameters = GeneratorHelpers.GetApiItemsFromReferenceTuple( + data.ApiItem.TypeParameters, + data.ExtractedData + ); + const resolvedTypeParametersDto = this.resolveFunctionTypeParameters(typeParameters); + + const resolvedReturnTypeDto = this.resolveReturnType(data.ApiItem.ReturnType); + + const builder = new MarkdownBuilder() + .Header(GeneratorHelpers.ApiFunctionToSimpleString(alias, data.ApiItem, parameters), 2) + .EmptyLine() + .Text(GeneratorHelpers.RenderApiItemMetadata(data.ApiItem)) + .Code(GeneratorHelpers.ApiFunctionToString( + data.ApiItem, + typeParameters, + parameters, + data.Reference.Alias + ), GeneratorHelpers.DEFAULT_CODE_OPTIONS) + .EmptyLine() + .Text(resolvedTypeParametersDto.Text) + .Text(resolvedParametersDto.Text) + .Text(resolvedReturnTypeDto.Text); + + return { + ApiItem: data.ApiItem, + Reference: data.Reference, + Headings: headings, + UsedReferences: [ + ...resolvedParametersDto.References, + ...resolvedTypeParametersDto.References, + ...resolvedReturnTypeDto.References + ], + Result: builder.GetOutput() + }; + } +} 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 9113bab0..c1d33630 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 @@ -1,12 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`index 1`] = ` +exports[`simple-project-1 1`] = ` Array [ Object { "FileLocation": "index.md", - "Output": Array [ - "# index", - "", + "Result": Array [ + "[ClassDeclaration-2]: index.md#class-earth", + "[ClassDeclaration-1]: index.md#class-world", "## EnumList", "", "Simple list.", @@ -28,7 +28,7 @@ Array [ "", "## EnumListWithNumberValues", "", - "List with number values with no punctuation at the end of description.", + "List with number values with no punctuation at the end of description", "", "", "\`\`\`typescript", @@ -47,9 +47,10 @@ Array [ "", "## EnumListWithStringValues", "", + "Warning: Beta!", + "", + "Deprecated!", "", - "beta", - "deprecated", "", "\`\`\`typescript", "enum EnumListWithStringValues {", @@ -77,6 +78,281 @@ Array [ "", "## class: Foo", "", + "## class: World", + "", + "## class: Earth", + "", + "## AnotherFoo(parameter1, parameter2)", + "", + "\`\`\`typescript", + "function AnotherFoo(parameter1: string, parameter2: Promise): string", + "\`\`\`", + "", + "### Type parameters", + "", + "| Name | Constraint type |", + "| ---- | --------------- |", + "| T | Object |", + "", + "### Parameters", + "", + "| Name | Type |", + "| ---------- | ------- |", + "| parameter1 | string |", + "| parameter2 | Promise |", + "", + "### Return type", + "", + "string", + "", + "", + "## GetFoo()", + "", + "\`\`\`typescript", + "function GetFoo(): Promise", + "\`\`\`", + "", + "### Return type", + "", + "Promise", + "", + "", + "## FunctionWithOneParameter(parameter)", + "", + "\`\`\`typescript", + "function FunctionWithOneParameter(parameter: string): void", + "\`\`\`", + "", + "### Parameters", + "", + "| Name | Type |", + "| --------- | ------ |", + "| parameter | string |", + "", + "### Return type", + "", + "void", + "", + "", + "## FunctionWithNoParameters()", + "", + "\`\`\`typescript", + "function FunctionWithNoParameters(): void", + "\`\`\`", + "", + "### Return type", + "", + "void", + "", + "", + "## FunctionWithMultipleParameters(parameter1, parameter2)", + "", + "\`\`\`typescript", + "function FunctionWithMultipleParameters(parameter1: string, parameter2: number): void", + "\`\`\`", + "", + "### Parameters", + "", + "| Name | Type |", + "| ---------- | ------ |", + "| parameter1 | string |", + "| parameter2 | number |", + "", + "### Return type", + "", + "void", + "", + "", + "## Bar(parameter1, parameter2)", + "", + "Warning: Beta!", + "", + "Deprecated!", + "", + "Some general comment about Bar function.", + "", + "\`\`\`typescript", + "function Bar(parameter1: string, parameter2: number): string", + "\`\`\`", + "", + "### Parameters", + "", + "| Name | Type |", + "| ---------- | ------ |", + "| parameter1 | string |", + "| parameter2 | number |", + "", + "### Return type", + "", + "string", + "", + "", + "## FunctionWithMultipleTypeParameters(parameter1, parameter2)", + "", + "Comment on Function with multiple type parameters.", + "", + "\`\`\`typescript", + "function FunctionWithMultipleTypeParameters(parameter1: T, parameter2: P): string", + "\`\`\`", + "", + "### Type parameters", + "", + "| Name | Constraint type |", + "| ---- | --------------- |", + "| T | Object |", + "| P | |", + "", + "### Parameters", + "", + "| Name | Type |", + "| ---------- | ---- |", + "| parameter1 | T |", + "| parameter2 | P |", + "", + "### Return type", + "", + "string", + "", + "", + "## FunctionWithTypeParameterDefault(parameter1, parameter2)", + "", + "Some general comment about Function with type parameter default function.", + "", + "\`\`\`typescript", + "function FunctionWithTypeParameterDefault(parameter1: string, parameter2: T): string", + "\`\`\`", + "", + "### Type parameters", + "", + "| Name | Constraint type | Default type |", + "| ---- | --------------- | ------------ |", + "| T | Object | \\\\{\\\\} |", + "", + "### Parameters", + "", + "| Name | Type |", + "| ---------- | ------ |", + "| parameter1 | string |", + "| parameter2 | T |", + "", + "### Return type", + "", + "string", + "", + "", + "## FunctionWithTypeParameterConstraint(parameter1, parameter2)", + "", + "Some general comment about AnotherBar function.", + "", + "\`\`\`typescript", + "function FunctionWithTypeParameterConstraint(parameter1: string, parameter2: T): string", + "\`\`\`", + "", + "### Type parameters", + "", + "| Name | Constraint type |", + "| ---- | --------------- |", + "| T | Object |", + "", + "### Parameters", + "", + "| Name | Type |", + "| ---------- | ------ |", + "| parameter1 | string |", + "| parameter2 | T |", + "", + "### Return type", + "", + "string", + "", + "", + "## FunctionWithoutReturnType(parameter1, parameter2)", + "", + "\`\`\`typescript", + "function FunctionWithoutReturnType(parameter1: string, parameter2: Promise): string", + "\`\`\`", + "", + "### Type parameters", + "", + "| Name | Constraint type |", + "| ---- | --------------- |", + "| T | Array |", + "", + "### Parameters", + "", + "| Name | Type |", + "| ---------- | ------- |", + "| parameter1 | string |", + "| parameter2 | Promise |", + "", + "### Return type", + "", + "string", + "", + "", + "## FunctionWithGenericReturnType()", + "", + "\`\`\`typescript", + "function FunctionWithGenericReturnType(): string[]", + "\`\`\`", + "", + "### Return type", + "", + "Array", + "", + "", + "## FunctionWithPrimitiveReturnType()", + "", + "\`\`\`typescript", + "function FunctionWithPrimitiveReturnType(): boolean", + "\`\`\`", + "", + "### Return type", + "", + "true | false", + "", + "", + "## FunctionWithUnionReturnType()", + "", + "\`\`\`typescript", + "function FunctionWithUnionReturnType(): \\"something\\" | \\"nothing\\"", + "\`\`\`", + "", + "### Return type", + "", + "\\"something\\" | \\"nothing\\"", + "", + "", + "## FunctionWithIntersectionReturnType()", + "", + "\`\`\`typescript", + "function FunctionWithIntersectionReturnType(): Earth & World", + "\`\`\`", + "", + "### Return type", + "", + "[Earth][ClassDeclaration-2] & [World][ClassDeclaration-1]", + "", + "", + "## MyFunction()", + "", + "Function with TypeParameter as TypeLiteral.", + "", + "\`\`\`typescript", + "function MyFunction(): T", + "\`\`\`", + "", + "### Type parameters", + "", + "| Name | Constraint type | Default type |", + "| ---- | -------------------------------------------------------------- | ------------------------- |", + "| T | \\\\{ myProperty: string; myPropertyTwo?: number \\\\| undefined; \\\\} | \\\\{ myProperty: string; \\\\} |", + "", + "### Return type", + "", + "T", + "", + "", ], }, ] 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 4939fde2..5ef537ea 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 @@ -1,12 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`index 1`] = ` +exports[`simple-project-2 1`] = ` Array [ Object { "FileLocation": "index.md", - "Output": Array [ - "# index", - "", + "Result": Array [ "## class: Foo", "", "## class: FooStart", @@ -15,9 +13,7 @@ Array [ }, Object { "FileLocation": "foo.md", - "Output": Array [ - "# foo", - "", + "Result": Array [ "## class: Foo", "", ], diff --git a/packages/ts-docs-gen/tests/cases/simple-project-1/index.ts b/packages/ts-docs-gen/tests/cases/simple-project-1/index.ts index c3a40955..eeaf5349 100644 --- a/packages/ts-docs-gen/tests/cases/simple-project-1/index.ts +++ b/packages/ts-docs-gen/tests/cases/simple-project-1/index.ts @@ -1,3 +1,4 @@ +// #region Enums /** * Simple list. */ @@ -35,6 +36,8 @@ export enum EnumListWithStringValues { ThirdOption = "third" } +// #endregion Enums + export const SampleConst: string = "sample-const"; export class Foo { @@ -42,3 +45,96 @@ export class Foo { return message; } } + +export class World { } +export class Earth { } + +// #region Functions + +export function AnotherFoo(parameter1: string, parameter2: Promise): string { + return "bar"; +} + +export async function GetFoo(): Promise { + return; +} + +export function FunctionWithOneParameter(parameter: string): void { + return; +} + +export function FunctionWithNoParameters(): void { + return; +} + +export function FunctionWithMultipleParameters(parameter1: string, parameter2: number): void { + return; +} + +/** + * Some general comment about Bar function. + * + * @beta Some comment on beta. + * @deprecated + */ +export function Bar(parameter1: string, parameter2: number): string { + return "bar"; +} + +/** + * Comment on Function with multiple type parameters. + * + * @template T Parameter T comment + * @template P Parameter P comment + * @param parameter1 Parameter one comment + * @param parameter2 Parameter two comment + * @returns Return type comment + */ +export function FunctionWithMultipleTypeParameters(parameter1: T, parameter2: P): string { + return "bar"; +} + +/** + * Some general comment about Function with type parameter default function. + */ +export function FunctionWithTypeParameterDefault(parameter1: string, parameter2: T): string { + return "bar"; +} + +/** + * Some general comment about AnotherBar function. + */ +export function FunctionWithTypeParameterConstraint(parameter1: string, parameter2: T): string { + return "bar"; +} + +export function FunctionWithoutReturnType(parameter1: string, parameter2: Promise): string { + return "bar"; +} + +export function FunctionWithGenericReturnType(): string[] { + return []; +} + +export function FunctionWithPrimitiveReturnType(): boolean { + return true; +} + +export function FunctionWithUnionReturnType(): "something" | "nothing" { + return "nothing"; +} + +export function FunctionWithIntersectionReturnType(): Earth & World { + return {}; +} + +/** + * Function with TypeParameter as TypeLiteral. + */ +export function MyFunction(): T { + return { + myProperty: "sampleString" + } as T; +} + +// #endregion Functions