Browse Source

feat(docs): Generate docs for function declarations

Relates to #89
Michael Bromley 6 years ago
parent
commit
4d99a714f1

+ 8 - 2
scripts/docs/typescript-docgen-types.ts

@@ -58,6 +58,12 @@ export interface EnumInfo extends DeclarationInfo {
     members: PropertyInfo[];
 }
 
-export type ParsedDeclaration = TypeAliasInfo | ClassInfo | InterfaceInfo | EnumInfo;
-export type ValidDeclaration = ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.ClassDeclaration | ts.EnumDeclaration;
+export interface FunctionInfo extends DeclarationInfo {
+    kind: 'function';
+    parameters: MethodParameterInfo[];
+    type?: ts.TypeNode;
+}
+
+export type ParsedDeclaration = TypeAliasInfo | ClassInfo | InterfaceInfo | EnumInfo | FunctionInfo;
+export type ValidDeclaration = ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.ClassDeclaration | ts.EnumDeclaration | ts.FunctionDeclaration;
 export type TypeMap = Map<string, string>;

+ 13 - 1
scripts/docs/typescript-docs-parser.ts

@@ -129,6 +129,17 @@ export class TypescriptDocsParser {
                 kind: 'enum' as 'enum',
                 members: this.parseMembers(statement.members) as PropertyInfo[],
             };
+        } else if (ts.isFunctionDeclaration(statement)) {
+            const parameters = statement.parameters.map(p => ({
+                name: p.name.getText(),
+                type: p.type ? p.type.getText() : '',
+            }));
+            return {
+                ...info,
+                kind: 'function',
+                parameters,
+                type: statement.type,
+            };
         }
     }
 
@@ -288,7 +299,8 @@ export class TypescriptDocsParser {
             ts.isInterfaceDeclaration(statement) ||
             ts.isTypeAliasDeclaration(statement) ||
             ts.isClassDeclaration(statement) ||
-            ts.isEnumDeclaration(statement)
+            ts.isEnumDeclaration(statement) ||
+            ts.isFunctionDeclaration(statement)
         );
     }
 

+ 53 - 1
scripts/docs/typescript-docs-renderer.ts

@@ -7,7 +7,16 @@ import ts from 'typescript';
 import { assertNever } from '../../packages/common/src/shared-utils';
 
 import { deleteGeneratedDocs, generateFrontMatter } from './docgen-utils';
-import { ClassInfo, DeclarationInfo, EnumInfo, InterfaceInfo, ParsedDeclaration, TypeAliasInfo, TypeMap } from './typescript-docgen-types';
+import {
+    ClassInfo,
+    DeclarationInfo,
+    EnumInfo,
+    FunctionInfo,
+    InterfaceInfo, MethodParameterInfo,
+    ParsedDeclaration,
+    TypeAliasInfo,
+    TypeMap,
+} from './typescript-docgen-types';
 
 export class TypescriptDocsRenderer {
 
@@ -31,6 +40,9 @@ export class TypescriptDocsRenderer {
                 case 'enum':
                     markdown = this.renderEnum(info, typeMap, docsUrl);
                     break;
+                case 'function':
+                    markdown = this.renderFunction(info, typeMap, docsUrl);
+                    break;
                 default:
                     assertNever(info);
             }
@@ -100,6 +112,22 @@ export class TypescriptDocsRenderer {
         return output;
     }
 
+    private renderFunction(functionInfo: FunctionInfo, knownTypeMap: TypeMap, docsUrl: string): string {
+        const { title, weight, description, fullText, parameters } = functionInfo;
+        let output = '';
+        output += generateFrontMatter(title, weight);
+        output += `\n\n# ${title}\n\n`;
+        output += this.renderGenerationInfoShortcode(functionInfo);
+        output += `${this.renderDescription(description, knownTypeMap, docsUrl)}\n\n`;
+        output += `## Signature\n\n`;
+        output += this.renderFunctionSignature(functionInfo, knownTypeMap);
+        if (parameters.length) {
+            output += `## Parameters\n\n`;
+            output += this.renderFunctionParams(parameters, knownTypeMap, docsUrl);
+        }
+        return output;
+    }
+
     /**
      * Generates a markdown code block string for the interface signature.
      */
@@ -189,6 +217,30 @@ export class TypescriptDocsRenderer {
         return output;
     }
 
+    private renderFunctionSignature(functionInfo: FunctionInfo, knownTypeMap: TypeMap): string {
+        const { fullText, parameters, type } = functionInfo;
+        const args = parameters
+                  .map(p => {
+                      return `${p.name}: ${p.type}`;
+                  })
+                  .join(', ');
+        let output = '';
+        output += `\`\`\`TypeScript\n`;
+        output += `function ${fullText}(${args}): ${type ? type.getText() : 'void'}\n`;
+        output += `\`\`\`\n`;
+        return output;
+    }
+
+    private renderFunctionParams(params: MethodParameterInfo[], knownTypeMap: TypeMap, docsUrl: string): string {
+        let output = '';
+        for (const param of params) {
+            const type = this.renderType(param.type, knownTypeMap, docsUrl);
+            output += `### ${param.name}\n\n`;
+            output += `{{< member-info kind="parameter" type="${type}" >}}\n\n`;
+        }
+        return output;
+    }
+
     private renderMembers(info: InterfaceInfo | ClassInfo | TypeAliasInfo | EnumInfo, knownTypeMap: TypeMap, docsUrl: string): string {
         const { members, title } = info;
         let output = '';