typedoc-plugin-markdown
Version:
A TypeDoc plugin that generates TypeScript API documentation as Markdown.
95 lines (94 loc) • 4.25 kB
JavaScript
import { backTicks, htmlTable, table } from '../../../libs/markdown/index.js';
import { removeLineBreaks } from '../../../libs/utils/index.js';
import { i18n, ReflectionKind, ReflectionType, } from 'typedoc';
export function parametersTable(model) {
const tableColumnsOptions = this.options.getValue('tableColumnSettings');
const leftAlignHeadings = tableColumnsOptions.leftAlignHeaders;
const parseParams = (current, acc) => {
const shouldFlatten = current.type?.declaration?.kind === ReflectionKind.TypeLiteral &&
current.type?.declaration?.children;
return shouldFlatten
? [...acc, current, ...flattenParams(current)]
: [...acc, current];
};
const flattenParams = (current) => {
return current.type?.declaration?.children?.reduce((acc, child) => {
const childObj = {
...child,
name: `${current.name}.${child.name}`,
};
return parseParams(childObj, acc);
}, []);
};
const showDefaults = !tableColumnsOptions.hideDefaults && hasDefaultValues(model);
const parsedParams = model.reduce((acc, current) => parseParams(current, acc), []);
const hasComments = parsedParams.some((param) => Boolean(getParameterComment(param)));
const headers = [
ReflectionKind.singularString(ReflectionKind.Parameter),
i18n.theme_type(),
];
if (showDefaults) {
headers.push(i18n.theme_default_value());
}
if (hasComments) {
headers.push(i18n.theme_description());
}
const firstOptionalParamIndex = model.findIndex((parameter) => parameter.flags.isOptional);
const rows = [];
parsedParams.forEach((parameter) => {
const row = [];
// A top-level parameter after the first optional one is itself optional,
// and so is one with a default value (as in the signature title and list
// format). Flattened members of an object parameter are copies, not in
// `model`, and are optional only by their own flag.
const index = model.indexOf(parameter);
const isOptional = parameter.flags.isOptional ||
Boolean(parameter.defaultValue) ||
(firstOptionalParamIndex !== -1 && index > firstOptionalParamIndex);
const rest = parameter.flags?.isRest ? '...' : '';
const optional = isOptional ? '?' : '';
row.push(`${rest}${backTicks(`${parameter.name}${optional}`)}`);
if (parameter.type) {
const displayType = parameter.type instanceof ReflectionType
? this.partials.reflectionType(parameter.type, {
forceCollapse: true,
})
: this.partials.someType(parameter.type);
row.push(removeLineBreaks(displayType));
}
else if (parameter.signatures?.length) {
// A method member of an object parameter has no type of its own.
row.push(removeLineBreaks(this.partials.functionType(parameter.signatures)));
}
if (showDefaults) {
row.push(backTicks(this.helpers.getParameterDefaultValue(parameter)));
}
if (hasComments) {
const comment = getParameterComment(parameter);
if (comment) {
const comments = this.partials.comment(comment, {
isTableColumn: true,
});
row.push(comments.length ? comments : '-');
}
else {
row.push('-');
}
}
rows.push(row);
});
return this.options.getValue('parametersFormat') == 'table'
? table(headers, rows, leftAlignHeadings)
: htmlTable(headers, rows, leftAlignHeadings);
}
// A method member of an object parameter keeps its comment on the signature.
function getParameterComment(parameter) {
return (parameter.comment ??
parameter.signatures?.find((signature) => signature.comment)?.comment);
}
function hasDefaultValues(parameters) {
const defaultValues = parameters.map((param) => param.defaultValue !== '{}' &&
param.defaultValue !== '...' &&
!!param.defaultValue);
return !defaultValues.every((value) => !value);
}