Skip to content

Commit f73cd67

Browse files
feat: set up initial behavior
1 parent 4dbaa8a commit f73cd67

File tree

4 files changed

+144
-3
lines changed

4 files changed

+144
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ node_modules/
22

33
/coverage/
44
/dist/
5+
/docs/
56

67
*.log

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,11 @@
9898
"rollup-plugin-dts": "5.2.0",
9999
"semantic-release": "20.1.0",
100100
"ts-node": "10.9.1",
101+
"typedoc": "^0.23.25",
101102
"typescript": "4.9.5"
102103
},
104+
"peerDependencies": {
105+
"typedoc": "^0.23.25"
106+
},
103107
"packageManager": "[email protected]"
104108
}

pnpm-lock.yaml

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,99 @@
1-
/* eslint-disable eslint-comments/disable-enable-pair */
2-
/* eslint-disable unicorn/no-empty-file */
1+
import type { Application, ProjectReflection, Reflection } from "typedoc";
2+
import { ParameterType, Validator, ReflectionKind } from "typedoc";
33

4-
// Write me
4+
/**
5+
* Extend typedoc's options with the plugin's option using declaration merging.
6+
*/
7+
declare module "typedoc" {
8+
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions, jsdoc/require-jsdoc
9+
export interface TypeDocOptionMap {
10+
requireTags: {
11+
byKind: ByKindEntry[];
12+
};
13+
}
14+
}
15+
16+
export type ByKindEntry = {
17+
kind: keyof typeof ReflectionKind;
18+
tags: string[];
19+
};
20+
21+
export function load(app: Readonly<Application>) {
22+
// @ts-expect-error -- FIXME: ???
23+
app.options.addDeclaration({
24+
name: "requireTags",
25+
help: "The configuration object of the require-tags plugin.",
26+
type: ParameterType.Object,
27+
});
28+
29+
app.validator.on(
30+
Validator.EVENT_RUN,
31+
(project: Readonly<ProjectReflection>) => {
32+
const requireTagsOptions = app.options.getValue(
33+
"requireTags"
34+
) as unknown as {
35+
byKind: ByKindEntry[];
36+
};
37+
38+
let m_kinds = requireTagsOptions.byKind.reduce(
39+
(prev, cur) => prev | ReflectionKind[cur.kind],
40+
0
41+
);
42+
43+
const reflectionKindReplacements: Array<
44+
[oldKind: number, newKind: number]
45+
> = [
46+
[ReflectionKind.FunctionOrMethod, ReflectionKind.CallSignature],
47+
[ReflectionKind.Constructor, ReflectionKind.ConstructorSignature],
48+
[
49+
ReflectionKind.Accessor,
50+
ReflectionKind.GetSignature | ReflectionKind.SetSignature,
51+
],
52+
];
53+
54+
for (const [oldKind, newKind] of reflectionKindReplacements) {
55+
m_kinds = (m_kinds | newKind) & ~oldKind;
56+
}
57+
58+
const requireTagsByKind = new Map<number, string[]>(
59+
requireTagsOptions.byKind.map(
60+
({ kind: kindString, tags }): [number, string[]] => {
61+
const kind = ReflectionKind[kindString];
62+
const realKind =
63+
reflectionKindReplacements.find(
64+
([oldKind]) => (oldKind & kind) !== 0
65+
)?.[1] ?? kind;
66+
return [realKind, tags];
67+
}
68+
)
69+
);
70+
71+
const reflections = project.getReflectionsByKind(m_kinds);
72+
const seen = new Set<Reflection>();
73+
74+
for (const reflection of reflections) {
75+
if (seen.has(reflection)) {
76+
continue;
77+
}
78+
79+
seen.add(reflection);
80+
81+
if (!reflection.hasComment()) {
82+
app.logger.warn(
83+
`${reflection.getFriendlyFullName()} does not have any documentation.`
84+
);
85+
continue;
86+
}
87+
88+
for (const tagName of requireTagsByKind.get(reflection.kind)!) {
89+
const tag = `@${tagName}` as const;
90+
if (reflection.comment!.getTags(tag).length === 0) {
91+
app.logger.warn(
92+
`${reflection.getFriendlyFullName()} does not have any ${tag} tags.`
93+
);
94+
}
95+
}
96+
}
97+
}
98+
);
99+
}

0 commit comments

Comments
 (0)