UNPKG

@jsdocs-io/extractor

Version:

The API extractor for npm packages powering jsdocs.io

112 lines (110 loc) 5.3 kB
import { orderBy } from "natural-orderby"; import { Node, } from "ts-morph"; import { ambientModulesDeclarations } from "./ambient-modules-declarations.js"; import { isClass, isEnum, isExpression, isFileModule, isFunction, isFunctionExpression, isInterface, isNamespace, isTypeAlias, isVariable, isVariableAssignmentExpression, } from "./declaration-type-guards.js"; import { exportEqualsDeclarations } from "./export-equals-declarations.js"; import { exportedDeclarations } from "./exported-declarations.js"; import { extractClass } from "./extract-class.js"; import { extractEnum } from "./extract-enum.js"; import { extractExpression } from "./extract-expression.js"; import { extractFileModule } from "./extract-file-module.js"; import { extractFunctionExpression } from "./extract-function-expression.js"; import { extractFunction } from "./extract-function.js"; import { extractInterface } from "./extract-interface.js"; import { extractNamespace } from "./extract-namespace.js"; import { extractTypeAlias } from "./extract-type-alias.js"; import { extractVariableAssignmentExpression } from "./extract-variable-assignment-expression.js"; import { extractVariable } from "./extract-variable.js"; import { globalAmbientDeclarations } from "./global-ambient-declarations.js"; import { id } from "./id.js"; /** `extractDeclarations` extracts the top-level declarations found in a container and/or a project. @param options - {@link ExtractDeclarationsOptions} */ export async function extractDeclarations({ containerName, container, maxDepth, project, pkgName, }) { const foundDeclarations = [ ...exportedDeclarations(containerName, container), ...exportEqualsDeclarations(containerName, container), ...(project ? ambientModulesDeclarations(containerName, project, pkgName) : []), ...(Node.isSourceFile(container) ? globalAmbientDeclarations(containerName, container) : []), ]; const seenFunctions = new Set(); const seenNamespaces = new Set(); const extractedDeclarations = []; for (const { containerName, exportName, declaration } of foundDeclarations) { const extractedDeclaration = await extractDeclaration({ containerName, exportName, declaration, maxDepth, seenFunctions, seenNamespaces, }); if (!extractedDeclaration) continue; extractedDeclarations.push(extractedDeclaration); } return orderBy(extractedDeclarations, "id"); } async function extractDeclaration({ containerName, exportName, declaration, maxDepth, seenFunctions, seenNamespaces, }) { if (isVariable(declaration)) { return await extractVariable(containerName, exportName, declaration); } if (isVariableAssignmentExpression(declaration)) { return await extractVariableAssignmentExpression(containerName, exportName, declaration); } if (isExpression(declaration)) { return await extractExpression(containerName, exportName, declaration); } if (isFunction(declaration)) { if (seenFunctions.has(exportName)) { // Skip function overloads, since an extracted function already contains // the docs and signatures of the implementation and all the overloads. return undefined; } seenFunctions.add(exportName); return await extractFunction(containerName, exportName, declaration); } if (isFunctionExpression(declaration)) { return await extractFunctionExpression(containerName, exportName, declaration); } if (isClass(declaration)) { return await extractClass(containerName, exportName, declaration); } if (isInterface(declaration)) { return await extractInterface(containerName, exportName, declaration); } if (isEnum(declaration)) { return await extractEnum(containerName, exportName, declaration); } if (isTypeAlias(declaration)) { return await extractTypeAlias(containerName, exportName, declaration); } if (isNamespace(declaration) && maxDepth > 0) { if (seenNamespaces.has(exportName)) { // Skip merged or nested namespaces, since an extracted namespace already // contains all the declarations found in the same namespace. return undefined; } seenNamespaces.add(exportName); const innerDeclarations = await extractDeclarations({ containerName: id(containerName, "+namespace", exportName), container: declaration, maxDepth: maxDepth - 1, }); return await extractNamespace(containerName, exportName, declaration, innerDeclarations); } if (isFileModule(declaration) && maxDepth > 0) { // A file module declaration happens with the following export forms: // `import * as ns from module; export { ns };` or // `export * as ns from module`. const innerDeclarations = await extractDeclarations({ containerName: id(containerName, "+namespace", exportName), container: declaration, maxDepth: maxDepth - 1, }); return await extractFileModule(containerName, exportName, declaration, innerDeclarations); } return undefined; }