Jelajahi Sumber

feat(docs): Allow variable statements to be documented

Michael Bromley 6 tahun lalu
induk
melakukan
60cc6000d4

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

@@ -74,6 +74,22 @@ export interface FunctionInfo extends DeclarationInfo {
     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 interface VariableInfo extends DeclarationInfo {
+    kind: 'variable';
+}
+
+export type ParsedDeclaration =
+    | TypeAliasInfo
+    | ClassInfo
+    | InterfaceInfo
+    | EnumInfo
+    | FunctionInfo
+    | VariableInfo;
+export type ValidDeclaration =
+    | ts.InterfaceDeclaration
+    | ts.TypeAliasDeclaration
+    | ts.ClassDeclaration
+    | ts.EnumDeclaration
+    | ts.FunctionDeclaration
+    | ts.VariableStatement;
 export type TypeMap = Map<string, string>;

+ 20 - 4
scripts/docs/typescript-docs-parser.ts

@@ -107,7 +107,12 @@ export class TypescriptDocsParser {
         if (category === undefined) {
             return;
         }
-        const title = statement.name ? statement.name.getText() : 'anonymous';
+        let title: string;
+        if (ts.isVariableStatement(statement)) {
+            title = statement.declarationList.declarations[0].name.getText();
+        } else {
+            title = statement.name ? statement.name.getText() : 'anonymous';
+        }
         const fullText = this.getDeclarationFullText(statement);
         const weight = this.getDeclarationWeight(statement);
         const description = this.getDeclarationDescription(statement);
@@ -169,6 +174,11 @@ export class TypescriptDocsParser {
                 parameters,
                 type: statement.type,
             };
+        } else if (ts.isVariableStatement(statement)) {
+            return {
+                ...info,
+                kind: 'variable',
+            };
         }
     }
 
@@ -194,9 +204,14 @@ export class TypescriptDocsParser {
      * Returns the declaration name plus any type parameters.
      */
     private getDeclarationFullText(declaration: ValidDeclaration): string {
-        const name = declaration.name ? declaration.name.getText() : 'anonymous';
+        let name: string;
+        if (ts.isVariableStatement(declaration)) {
+            name = declaration.declarationList.declarations[0].name.getText();
+        } else {
+            name = declaration.name ? declaration.name.getText() : 'anonymous';
+        }
         let typeParams = '';
-        if (!ts.isEnumDeclaration(declaration) && declaration.typeParameters) {
+        if (!ts.isEnumDeclaration(declaration) && !ts.isVariableStatement(declaration) && declaration.typeParameters) {
             typeParams = '<' + declaration.typeParameters.map(tp => tp.getText()).join(', ') + '>';
         }
         return name + typeParams;
@@ -348,7 +363,8 @@ export class TypescriptDocsParser {
             ts.isTypeAliasDeclaration(statement) ||
             ts.isClassDeclaration(statement) ||
             ts.isEnumDeclaration(statement) ||
-            ts.isFunctionDeclaration(statement)
+            ts.isFunctionDeclaration(statement) ||
+            ts.isVariableStatement(statement)
         );
     }
 

+ 15 - 3
scripts/docs/typescript-docs-renderer.ts

@@ -15,7 +15,7 @@ import {
     InterfaceInfo, MethodParameterInfo,
     ParsedDeclaration,
     TypeAliasInfo,
-    TypeMap,
+    TypeMap, VariableInfo,
 } from './typescript-docgen-types';
 
 export class TypescriptDocsRenderer {
@@ -47,6 +47,9 @@ export class TypescriptDocsRenderer {
                     case 'function':
                         markdown += this.renderFunction(info, typeMap, docsUrl);
                         break;
+                    case 'variable':
+                        markdown += this.renderVariable(info, typeMap, docsUrl);
+                        break;
                     default:
                         assertNever(info);
                 }
@@ -126,12 +129,21 @@ export class TypescriptDocsRenderer {
         output += `## Signature\n\n`;
         output += this.renderFunctionSignature(functionInfo, knownTypeMap);
         if (parameters.length) {
-            output += `### Parameters\n\n`;
+            output += `## Parameters\n\n`;
             output += this.renderFunctionParams(parameters, knownTypeMap, docsUrl);
         }
         return output;
     }
 
+    private renderVariable(variableInfo: VariableInfo, knownTypeMap: TypeMap, docsUrl: string): string {
+        const { title, weight, description, fullText } = variableInfo;
+        let output = '';
+        output += `\n\n# ${title}\n\n`;
+        output += this.renderGenerationInfoShortcode(variableInfo);
+        output += `${this.renderDescription(description, knownTypeMap, docsUrl)}\n\n`;
+        return output;
+    }
+
     /**
      * Generates a markdown code block string for the interface signature.
      */
@@ -303,7 +315,7 @@ export class TypescriptDocsRenderer {
     private renderDescription(description: string, knownTypeMap: TypeMap, docsUrl: string): string {
         for (const [key, val] of knownTypeMap) {
             const re = new RegExp(`{@link\\s*${key}}`, 'g');
-            description = description.replace(re, `<a href='${docsUrl}/${val}/'>${key}</a>`);
+            description = description.replace(re, `<a href='${docsUrl}/${val}'>${key}</a>`);
         }
         return description;
     }