Skip to content

Commit e72176d

Browse files
committed
fix: render constructors as \new ClassName(params)\ format (closes #2)
1 parent 2771c0e commit e72176d

1 file changed

Lines changed: 160 additions & 4 deletions

File tree

plugins/theme/index.mjs

Lines changed: 160 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,171 @@ export class DocKitTheme extends MarkdownTheme {
1212
}
1313

1414
export class DocKitThemeContext extends MarkdownThemeContext {
15-
helpers = helpers(this);
15+
helpers = {
16+
...this.helpers,
1617

17-
partials = partials(this);
18+
/** @param {import('typedoc').ParameterReflection} */
19+
typedListItem: ({ label, name, type, comment }) => {
20+
const namePart = label ? ` ${label}:` : name ? ` \`${name}\`` : "";
21+
const typePart = type
22+
? ` ${typeof type === "string" ? type : this.partials.someType(type)}`
23+
: "";
24+
const descPart = comment
25+
? ` ${this.helpers.getCommentParts(comment.summary ?? comment.content)}`
26+
: "";
1827

19-
templates = {
20-
...this.templates,
28+
return `*${namePart}${typePart}${descPart}`;
29+
},
30+
31+
typedList: (entries) => entries.map(this.helpers.typedListItem).join("\n"),
32+
};
33+
partials = {
34+
...this.partials,
35+
...typePartials,
36+
37+
constructor: (model, options) => {
38+
return model.signatures?.map(signature => {
39+
const params = signature.parameters ?? [];
40+
const className = model.parent?.name ?? "Unknown";
41+
const allOptional = params.length > 0 &&
42+
params.every(p => p.flags?.isOptional);
43+
const paramStr = allOptional
44+
? `[${params.map(p => p.name).join(", ")}]`
45+
: params.map(p =>
46+
p.flags?.isOptional ? `[${p.name}]` : p.name
47+
).join(", ");
48+
const title = `\`new ${className}(${paramStr})\``;
49+
const paramsList = params.length
50+
? this.helpers.typedList(params)
51+
: "";
52+
return [
53+
`#### ${title}`,
54+
paramsList,
55+
].filter(Boolean).join("\n");
56+
}).join("\n\n") ?? "";
57+
},
58+
// Removes *** horizontal rules between members
59+
members: (model, options) => {
60+
const items = model.filter(
61+
(item) => !this.router.hasOwnDocument(item)
62+
);
63+
return items
64+
.map(item =>
65+
this.partials.memberContainer(item, {
66+
headingLevel: options.headingLevel,
67+
groupTitle: options.groupTitle,
68+
})
69+
)
70+
.filter(Boolean)
71+
.join("\n\n");
72+
},
73+
74+
// Removes ### Constructors / ### Methods / ### Properties headings
75+
groups: (model, options) => {
76+
return (model.groups ?? [])
77+
.flatMap(group => {
78+
// Skip properties — already shown in constructor params
79+
const isPropertiesGroup = group.children?.every(
80+
child => child.kind === ReflectionKind.Property
81+
);
82+
if (isPropertiesGroup) return [];
83+
84+
const children = group.children?.filter(
85+
child => child.isDeclaration()
86+
) ?? [];
87+
if (!children.length) return [];
88+
89+
return [
90+
this.partials.members(children, {
91+
headingLevel: options.headingLevel,
92+
groupTitle: group.title,
93+
})
94+
];
95+
})
96+
.filter(Boolean)
97+
.join("\n\n");
98+
},
99+
100+
body: (model, options) => {
101+
if (model.groups?.length) {
102+
return this.partials.groups(model, {
103+
headingLevel: options.headingLevel,
104+
kind: model.kind,
105+
});
106+
}
107+
return "";
108+
},
109+
110+
// Typed Lists
111+
parametersList: this.helpers.typedList,
112+
propertiesTable: this.helpers.typedList,
113+
signature: (model, options) => {
114+
const comment = options.multipleSignatures
115+
? model.comment
116+
: model.comment || model.parent?.comment;
117+
118+
return [
119+
model.typeParameters?.length &&
120+
this.partials.typeParametersList(model.typeParameters, {
121+
headingLevel: options.headingLevel,
122+
}),
123+
model.parameters?.length &&
124+
this.partials.parametersList(model.parameters, {
125+
headingLevel: options.headingLevel,
126+
}),
127+
this.helpers.typedListItem({
128+
label: "Returns",
129+
type: model.type ?? "void",
130+
comment: model.comment?.getTag("@returns"),
131+
}),
132+
"",
133+
comment &&
134+
this.partials.comment(comment, {
135+
headingLevel: options.headingLevel,
136+
}),
137+
]
138+
.filter((x) => (typeof x === "string" ? x : Boolean(x)))
139+
.join("\n");
140+
},
141+
142+
// Titles
143+
memberTitle: (model) => {
144+
//DEBUG
145+
// console.log("KIND:", model.kind, "NAME:", model.name, "CONSTRUCTOR KIND:", ReflectionKind.Constructor);
146+
147+
const prefix = resolveMemberPrefix(model);
148+
const params = model.signatures?.[0]?.parameters ?? null;
149+
const name = params
150+
? `\`${model.name}(${params.map((p) => p.name).join(", ")})\``
151+
: `\`${model.name}\``;
152+
return prefix ? `${prefix}: ${name}` : name;
153+
},
154+
declarationTitle: (model) => {
155+
return this.helpers.typedListItem({
156+
name: model.name,
157+
type: model.type,
158+
comment: model.comment,
159+
});
160+
},
161+
memberContainer: (model, options) => {
162+
const md = [];
163+
if (!this.router.hasOwnDocument(model) &&
164+
![ReflectionKind.Constructor].includes(model.kind)) {
165+
md.push(
166+
"#".repeat(options.headingLevel) + " " +
167+
this.partials.memberTitle(model)
168+
);
169+
}
170+
md.push(this.partials.member(model, {
171+
headingLevel: options.headingLevel + 1, // ← methods get ####
172+
nested: options.nested,
173+
}));
174+
return md.filter(Boolean).join("\n\n");
175+
},
21176
};
22177
}
23178

179+
/** @param {import('typedoc').Application} app */
24180
export function load(app) {
25181
app.renderer.defineTheme('doc-kit', DocKitTheme);
26182
}

0 commit comments

Comments
 (0)