Add generated API documentation site POC#209
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces an automated documentation generation system for the utility-types library. It adds a new script, scripts/generate-api-docs.js, which leverages the TypeScript compiler API to extract type definitions, JSDoc comments, and examples into Markdown files for a Docsify-powered documentation site. Feedback includes addressing a potential crash in the generation script when the entry point is missing, improving the robustness of function snippet extraction, and correcting minor syntax and content errors in the generated documentation files.
| var index = program.getSourceFile(path.join(srcDir, 'index.ts')); | ||
| var moduleSymbol = checker.getSymbolAtLocation(index); |
There was a problem hiding this comment.
If src/index.ts is missing or cannot be read by the TypeScript program, program.getSourceFile will return undefined. This will cause the script to crash with a TypeError when calling checker.getSymbolAtLocation(index) on the following line. A defensive check should be added.
var indexFile = path.join(srcDir, 'index.ts');
var index = program.getSourceFile(indexFile);
if (!index) {
throw new Error('Could not find entry point: ' + indexFile);
}
var moduleSymbol = checker.getSymbolAtLocation(index);|
|
||
| ## `Nullish` | ||
|
|
||
| Type representing [nullish values][https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing] in TypeScript: `null | undefined` |
There was a problem hiding this comment.
The markdown link syntax for the TypeScript handbook is incorrect. It uses square brackets for both parts [text][url], which is not standard for inline links.
| Type representing [nullish values][https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing] in TypeScript: `null | undefined` | |
| Type representing [nullish values](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing) in TypeScript: `null | undefined` |
|
|
||
| ```ts | ||
| // Expect: "string | null" | ||
| SymmetricDifference<string | null | undefined>; |
| type DefaultProps = { age: number }; | ||
|
|
||
| // Expect: { name: string; visible: boolean; } | ||
| type RequiredProps = Diff<Props, DefaultProps>; |
There was a problem hiding this comment.
The example for $Diff incorrectly uses the Diff type instead of $Diff. This should be corrected in the source JSDoc in src/utility-types.ts to ensure the documentation accurately reflects the utility being described.
| type RequiredProps = Diff<Props, DefaultProps>; | |
| type RequiredProps = $Diff<Props, DefaultProps>; |
| function getDeclarationSnippet(declaration, publicName, checker) { | ||
| if (ts.isVariableDeclaration(declaration)) { | ||
| var type = checker.typeToString(checker.getTypeAtLocation(declaration.name)); | ||
| return 'export const ' + publicName + ': ' + type + ';'; | ||
| } | ||
|
|
||
| return trimImplementation(declaration.getText(declaration.getSourceFile())); | ||
| } |
There was a problem hiding this comment.
The current implementation of getDeclarationSnippet relies on a fragile trimImplementation function that only handles arrow functions with a specific block format (=> {). It fails to trim the body of regular function declarations (like getReturnOfExpression), causing implementation details to leak into the documentation. Using the TypeScript compiler API to identify the function body is more robust.
function getDeclarationSnippet(declaration, publicName, checker) {
if (ts.isVariableDeclaration(declaration)) {
var type = checker.typeToString(checker.getTypeAtLocation(declaration.name));
return 'export const ' + publicName + ': ' + type + ';';
}
var sourceFile = declaration.getSourceFile();
var text = declaration.getText(sourceFile);
var stripped = stripJsDoc(text).trim();
if (ts.isFunctionDeclaration(declaration) && declaration.body) {
var bodyStart = declaration.body.getStart(sourceFile);
var nodeStart = declaration.getStart(sourceFile);
return stripped.slice(0, bodyStart - nodeStart).trim() + ';';
}
var arrowIndex = stripped.indexOf('=> {');
if (arrowIndex !== -1) {
return stripped.slice(0, arrowIndex + 2).trim() + ' ...';
}
return stripped;
}|
Addressed the Gemini review feedback in 13ddb05:
Validation:
This follow-up was prepared with AI assistance and manually reviewed before pushing. |
Summary
Fixes #30.
This adds a working proof-of-concept for generated API docs that follows the direction discussed in the issue:
src/index.tswith the existing TypeScript compiler dependencydocs/api/npm run docs:apiso docs can be refreshed after API/JSDoc changesI avoided Typedoc here because the issue discussion called out its UX/search/export-name problems. This POC keeps the generated output markdown-based and handles public re-export names such as
Requiredwhile still noting their source declaration when aliased.Validation
npm run docs:apinpm run ci-checkgit diff --checkdocs/locally and verified the Docsify sidebar/search flow withDeepReadonlyprettier:fix,lint,tsc, andtest:updateTransparency
This PR was prepared with AI assistance. I reviewed the generated code and docs locally, ran the validation above, and kept the change limited to the documentation POC for the funded IssueHunt issue.
IssueHunt Summary
Referenced issues
This pull request has been submitted to: