@jsdocs-io/extractor
Version:
The API extractor for npm packages powering jsdocs.io
112 lines (110 loc) • 5.3 kB
JavaScript
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;
}