include exclude tag default option comment children reference filter
Is it possible to have a custom tag to explicitly mark items and generate a documentation that output those items and any related types (children, reference, etc...)?
I found the issue #2028, which give me a good hint on how to do this. With the #2028 everything to include needs to be marked with the tag. I am trying to automate the inclusion of the types related to the one marked.
ex:
/**
* @include
*/
interface IncludedInterface {
parameters: SomeParameterRecord;
}
/**
* should be included
*/
type SomeParameterRecord = Record<string, ParameterValue>;
/**
* should be included
*/
type ParameterValue = BooleanParameter | AlignmentParameter;
/**
* should be included
*/
interface BooleanParameter {
value: boolean;
}
/**
* should be included
*/
type AlignmentParameterValue = 'left' | 'center' | 'right';
/**
* should be included
*/
interface AlignmentParameter {
value: AlignmentParameterValue;
}
/**
* should not be included
*/
interface NotIncludedInterface {[
parameters: SomeParameterRecord;
otherProperty: OtherPropertyInterface
}
/**
* should not be included
*/
interface OtherPropertyInterface {
key: string
}
Reflection.traverse give me some children but it seems to be not enough.
Any pointer to achieve would be greatly appreciated.
Started writing out how I'd do it... then realized it'd be easier to follow if I just did it, and would probably take less time
I added a few test cases:
/** @include */
function foo<TP extends Ext = Def>(prop: ParamRef): RetRef {
throw 1;
}
/** yes */
interface ParamRef {}
/** yes */
interface RetRef {}
/** yes */
interface Ext {}
/** yes */
interface Def {}
/** @include */
declare function overloaded(): string;
declare function overloaded(x: string): NotIncluded;
declare function overloadedFullyRemoved(): string;
declare function overloadedFullyRemoved(x: string): NotIncluded;
interface NotIncluded {}
And here's the plugin:
// @ts-check
// CC0
const td = require("typedoc");
/** @param {td.Application} app */
exports.load = function (app) {
// Optional: Automatically add `@include` as a modifier tag so that the user
// of this plugin doesn't have to. Do this with a low priority so that if the
// user sets the option anywhere, their choice will overwrite the default.
app.options.addReader({
name: "include-plugin",
priority: 0,
read(options) {
options.setValue("modifierTags", [
...options.getValue("modifierTags"),
"@include",
]);
},
});
app.converter.on(
td.Converter.EVENT_RESOLVE_BEGIN,
/** @param {td.Context} context */
(context) => {
for (const refl of discoverReflectionsToRemove(context.project)) {
context.project.removeReflection(refl);
}
}
);
};
/** @param {td.ProjectReflection} project */
function discoverReflectionsToRemove(project) {
/** @type {Set<td.Reflection>} */
const toRemove = new Set();
/** @type {Array<td.Reflection>} */
const retain = [];
/** @type {Array<td.DeclarationReflection>} */
const signatureContainers = [];
// First, separate by whether or not the reflection is tagged with @include
for (const refl of Object.values(project.reflections)) {
if (
!(
refl instanceof td.DeclarationReflection ||
refl instanceof td.SignatureReflection
)
) {
continue;
}
// Never filter the project itself, or an entry point.
if (refl.kindOf(td.ReflectionKind.Project | td.ReflectionKind.Module)) {
continue;
}
// Handle these at the end, they don't have comments and should be removed if all signatures will be removed
if (refl instanceof td.DeclarationReflection && refl.signatures) {
signatureContainers.push(refl);
continue;
}
if (refl.comment?.hasModifier("@include")) {
retain.push(refl);
} else {
toRemove.add(refl);
}
}
const visitor = td.makeRecursiveVisitor({
reference(type) {
if (type.reflection) {
retain.push(type.reflection);
}
},
});
// Now, for anything we're keeping, loop through its children and type references
// and remove them from the list of things to remove.
let refl = retain.shift();
while (refl) {
toRemove.delete(refl);
refl.comment?.removeModifier("@include");
if (refl instanceof td.DeclarationReflection) {
refl.type?.visit(visitor);
retain.push(...(refl.children || []));
retain.push(...(refl.typeParameters || []));
} else if (refl instanceof td.SignatureReflection) {
refl.type?.visit(visitor);
retain.push(...(refl.parameters || []));
retain.push(...(refl.typeParameters || []));
} else if (refl instanceof td.ParameterReflection) {
refl.type?.visit(visitor);
} else if (refl instanceof td.TypeParameterReflection) {
refl.type?.visit(visitor);
refl.default?.visit(visitor);
}
refl = retain.shift();
}
// Now handle declarations which contain signatures, and remove them if
// we're removing all the signatures.
for (const refl of signatureContainers) {
if (refl.signatures?.every((sig) => toRemove.has(sig))) {
toRemove.add(refl);
}
}
return toRemove;
}
Awesome!
that's perfect thanks so much @Gerrit0 !
Owner Name | TypeStrong |
Repo Name | typedoc |
Full Name | TypeStrong/typedoc |
Language | TypeScript |
Created Date | 2014-05-24 |
Updated Date | 2023-03-19 |
Star Count | 6487 |
Watcher Count | 68 |
Fork Count | 639 |
Issue Count | 48 |
Issue Title | Created Date | Updated Date |
---|