@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
149 lines (135 loc) • 5.69 kB
JavaScript
import { formatParameters, parseMarkdownToHast, applyDescriptionReplacements } from "./format.mjs";
import { formatType } from "./formatType.mjs";
import { isClassType } from "./typeGuards.mjs";
import { rewriteTypeStringsDeep } from "./rewriteTypes.mjs";
/**
* Class type from typescript-api-extractor.
* Defined here since ClassNode may not be exported from older versions.
*/
/**
* Formatted class metadata with plain text types and parsed markdown descriptions.
*
* Type highlighting (type → HAST, shortType, detailedType) is deferred to
* the loadServerTypes stage via highlightTypesMeta() after highlightTypes().
*/
/**
* Formatted property metadata for class properties.
*/
/**
* Formatted method metadata for class methods.
*/
/**
* Formats class export data into a structured metadata object.
*
* @param classExport - The class export node from typescript-api-extractor
* @param typeNameMap - Map for transforming type names
* @param rewriteContext - Context for type string rewriting including type compatibility map
* @param options - Formatting options
* @returns Formatted class metadata with constructor and methods
*/
export async function formatClassData(classExport, typeNameMap, rewriteContext, options = {}) {
const {
descriptionReplacements,
formatting,
externalTypes
} = options;
const {
exportNames
} = rewriteContext;
// Cast to ClassNode since we've verified via isPublicClass
const classType = classExport.type;
const descriptionText = classExport.documentation?.description ? applyDescriptionReplacements(classExport.documentation.description, descriptionReplacements) : undefined;
const description = descriptionText ? await parseMarkdownToHast(descriptionText) : undefined;
// Get the first construct signature for constructor parameters
const constructSignature = classType.constructSignatures[0];
const constructorParams = constructSignature?.parameters ?? [];
const constructorParameters = await formatParameters(constructorParams, {
exportNames,
typeNameMap,
formatting,
externalTypes,
descriptionReplacements
});
// Format properties
const propertyEntries = await Promise.all(classType.properties.map(async prop => {
const propDescriptionText = prop.documentation?.description ? applyDescriptionReplacements(prop.documentation.description, descriptionReplacements) : undefined;
const propDescription = propDescriptionText ? await parseMarkdownToHast(propDescriptionText) : undefined;
const typeText = formatType(prop.type, {
expandObjects: true,
exportNames,
typeNameMap,
externalTypesCollector: externalTypes
});
const formattedProperty = {
name: prop.name,
typeText,
description: propDescription,
descriptionText: propDescriptionText,
optional: prop.optional,
readonly: prop.readonly,
isStatic: prop.isStatic ?? false
};
return [prop.name, formattedProperty];
}));
const properties = Object.fromEntries(propertyEntries);
// Format methods in parallel to avoid eslint no-await-in-loop
const methodEntries = await Promise.all(classType.methods.map(async method => {
const methodDescriptionText = method.documentation?.description ? applyDescriptionReplacements(method.documentation.description, descriptionReplacements) : undefined;
const methodDescription = methodDescriptionText ? await parseMarkdownToHast(methodDescriptionText) : undefined;
// Use the first call signature (we don't support overloads in docs yet)
const signature = method.callSignatures?.[0];
const methodParameters = await formatParameters(signature?.parameters ?? [], {
exportNames,
typeNameMap,
formatting,
externalTypes,
descriptionReplacements
});
const returnValue = signature ? formatType(signature.returnValueType, {
expandObjects: true,
exportNames,
typeNameMap,
externalTypesCollector: externalTypes
}) : 'void';
// Get return value description from @returns tag if available
const returnsTag = method.documentation?.tags?.find(tag => tag.name === 'returns');
const returnValueDescriptionText = returnsTag?.value;
const returnValueDescription = returnValueDescriptionText ? await parseMarkdownToHast(returnValueDescriptionText) : undefined;
const formattedMethod = {
name: method.name,
description: methodDescription,
descriptionText: methodDescriptionText,
parameters: methodParameters,
returnValue,
returnValueDescription,
returnValueDescriptionText,
isStatic: method.isStatic ?? false
};
return [method.name, formattedMethod];
}));
const methods = Object.fromEntries(methodEntries);
// Extract type parameter names
const typeParameters = classType.typeParameters?.map(tp => tp.toString());
const raw = {
name: classExport.name,
description,
descriptionText,
constructorParameters,
properties,
methods,
typeParameters
};
// Post-process type strings to align naming across re-exports
return rewriteTypeStringsDeep(raw, rewriteContext);
}
/**
* Type guard to check if an export node is a public class.
*
* @param exportNode - The export node to check
* @returns true if the export is a public class that should be documented
*/
export function isPublicClass(exportNode) {
const isPublic = exportNode.documentation?.visibility !== 'private' && exportNode.documentation?.visibility !== 'internal';
const hasIgnoreTag = exportNode.documentation?.tags?.some(tag => tag.name === 'ignore');
return isClassType(exportNode.type) && !hasIgnoreTag && isPublic;
}