From 991b4ee29d109b3ccadf64b0567fe7a41385e63d Mon Sep 17 00:00:00 2001 From: Katari Date: Sat, 14 Mar 2026 01:32:56 +0530 Subject: [PATCH 1/7] feat(processor): append @example tags to reflection summary body --- plugins/processor.mjs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/plugins/processor.mjs b/plugins/processor.mjs index 8426aa5..b5556bf 100644 --- a/plugins/processor.mjs +++ b/plugins/processor.mjs @@ -27,6 +27,33 @@ export function load(app) { .forEach((namespace) => context.project.mergeReflections(namespace, namespace.parent), ); + + // Append examples to the body of members + context.project + .getReflectionsByKind(ReflectionKind.All) + .forEach((reflection) => { + if (reflection.comment) { + const examples = reflection.comment.blockTags.filter( + (tag) => tag.tag === "@example", + ); + if (examples.length > 0) { + if (reflection.comment.summary.length > 0) { + reflection.comment.summary.push({ kind: "text", text: "\n\n" }); + } + + examples.forEach((example, index) => { + reflection.comment.summary.push(...example.content); + if (index < examples.length - 1) { + reflection.comment.summary.push({ kind: "text", text: "\n\n" }); + } + }); + + reflection.comment.blockTags = reflection.comment.blockTags.filter( + (tag) => tag.tag !== "@example", + ); + } + } + }); }); app.renderer.on(Renderer.EVENT_END, (context) => { From 5c8daca54f9b4d33b7f0a4356495e19db5c28777 Mon Sep 17 00:00:00 2001 From: Katari Date: Sat, 14 Mar 2026 02:16:24 +0530 Subject: [PATCH 2/7] migrate code from processor to theme --- plugins/processor.mjs | 27 ------- plugins/theme/helpers/index.mjs | 14 +++- plugins/theme/partials/index.mjs | 128 +++++++++++++++++-------------- 3 files changed, 83 insertions(+), 86 deletions(-) diff --git a/plugins/processor.mjs b/plugins/processor.mjs index b5556bf..8426aa5 100644 --- a/plugins/processor.mjs +++ b/plugins/processor.mjs @@ -27,33 +27,6 @@ export function load(app) { .forEach((namespace) => context.project.mergeReflections(namespace, namespace.parent), ); - - // Append examples to the body of members - context.project - .getReflectionsByKind(ReflectionKind.All) - .forEach((reflection) => { - if (reflection.comment) { - const examples = reflection.comment.blockTags.filter( - (tag) => tag.tag === "@example", - ); - if (examples.length > 0) { - if (reflection.comment.summary.length > 0) { - reflection.comment.summary.push({ kind: "text", text: "\n\n" }); - } - - examples.forEach((example, index) => { - reflection.comment.summary.push(...example.content); - if (index < examples.length - 1) { - reflection.comment.summary.push({ kind: "text", text: "\n\n" }); - } - }); - - reflection.comment.blockTags = reflection.comment.blockTags.filter( - (tag) => tag.tag !== "@example", - ); - } - } - }); }); app.renderer.on(Renderer.EVENT_END, (context) => { diff --git a/plugins/theme/helpers/index.mjs b/plugins/theme/helpers/index.mjs index 880933e..9052684 100644 --- a/plugins/theme/helpers/index.mjs +++ b/plugins/theme/helpers/index.mjs @@ -21,7 +21,7 @@ export default (ctx) => ({ : ""; const descPart = comment - ? ` ${ctx.helpers.getCommentParts(comment.summary ?? comment.content)}` + ? ` ${ctx.helpers.getCommentParts(comment.summary ?? comment.content)}${ctx.helpers.renderExamples(comment)}` : ""; return `*${namePart}${typePart}${descPart}`; @@ -64,4 +64,16 @@ export default (ctx) => ({ return null; }, + + renderExamples(comment) { + if (!comment || !comment.blockTags) return ""; + const examples = comment.blockTags.filter((tag) => tag.tag === "@example"); + if (!examples.length) return ""; + return ( + "\n\n" + + examples + .map((tag) => ctx.helpers.getCommentParts(tag.content).trim()) + .join("\n\n") + ); + }, }); diff --git a/plugins/theme/partials/index.mjs b/plugins/theme/partials/index.mjs index 56463fb..36b0f32 100644 --- a/plugins/theme/partials/index.mjs +++ b/plugins/theme/partials/index.mjs @@ -27,70 +27,82 @@ export const getMemberPrefix = (model) => { * @param {import('typedoc-plugin-markdown').MarkdownThemeContext} ctx * @returns {import('typedoc-plugin-markdown').MarkdownThemeContext['partials']} */ -export default (ctx) => ({ - ...ctx.partials, - ...typePartials, +export default (ctx) => { + const baseComment = ctx.partials.comment; - signature(model, options) { - const comment = options.multipleSignatures - ? model.comment - : model.comment || model.parent?.comment; + return { + ...ctx.partials, + ...typePartials, - const stability = ctx.helpers.stabilityBlockquote(comment); + comment(model, options) { + return ( + baseComment.call(ctx, model, { ...options, showTags: false }) + + ctx.helpers.renderExamples(model) + ); + }, - return [ - stability, - stability && "", - model.typeParameters?.length && - ctx.partials.typeParametersList(model.typeParameters, { - headingLevel: options.headingLevel, - }), - model.parameters?.length && - ctx.partials.parametersList(model.parameters, { - headingLevel: options.headingLevel, - }), - ctx.helpers.typedListItem({ - label: "Returns", - type: model.type ?? "void", - comment: model.comment?.getTag("@returns"), - }), - "", - comment && - ctx.partials.comment(comment, { - headingLevel: options.headingLevel, - showTags: false, + signature(model, options) { + const comment = options.multipleSignatures + ? model.comment + : model.comment || model.parent?.comment; + + const stability = ctx.helpers.stabilityBlockquote(comment); + + return [ + stability, + stability && "", + model.typeParameters?.length && + ctx.partials.typeParametersList(model.typeParameters, { + headingLevel: options.headingLevel, + }), + model.parameters?.length && + ctx.partials.parametersList(model.parameters, { + headingLevel: options.headingLevel, + }), + ctx.helpers.typedListItem({ + label: "Returns", + type: model.type ?? "void", + comment: model.comment?.getTag("@returns"), }), - ] - .filter((x) => typeof x === "string" || Boolean(x)) - .join("\n"); - }, + "", + comment && + baseComment.call(ctx, comment, { + headingLevel: options.headingLevel, + showTags: false, + }), + ctx.helpers.renderExamples(comment), + ] + .filter((x) => typeof x === "string" || Boolean(x)) + .join("\n"); + }, - memberTitle(model) { - const prefix = getMemberPrefix(model); - const params = model.signatures?.[0]?.parameters; + memberTitle(model) { + const prefix = getMemberPrefix(model); + const params = model.signatures?.[0]?.parameters; - if (!params) { - return `${prefix}\`${model.name}\``; - } + if (!params) { + return `${prefix}\`${model.name}\``; + } - const paramsString = params - .map((param, index) => { - const paramName = param.name; - if (param.flags?.isOptional) { - // For optional params, wrap comma + name in brackets (except for first param) - return index === 0 ? `[${paramName}]` : `[, ${paramName}]`; - } else { - // For required params, add comma separator (except for first param) - return index === 0 ? paramName : `, ${paramName}`; - } - }) - .join(""); + const paramsString = params + .map((param, index) => { + const paramName = param.name; + if (param.flags?.isOptional) { + // For optional params, wrap comma + name in brackets (except for first param) + return index === 0 ? `[${paramName}]` : `[, ${paramName}]`; + } else { + // For required params, add comma separator (except for first param) + return index === 0 ? paramName : `, ${paramName}`; + } + }) + .join(""); - return `${prefix}\`${model.name}(${paramsString})\``; - }, + return `${prefix}\`${model.name}(${paramsString})\``; + }, - parametersList: ctx.helpers.typedList, - typedParametersList: ctx.helpers.typedList, - typeDeclarationList: ctx.helpers.typedList, - propertiesTable: ctx.helpers.typedList, -}); + parametersList: ctx.helpers.typedList, + typedParametersList: ctx.helpers.typedList, + typeDeclarationList: ctx.helpers.typedList, + propertiesTable: ctx.helpers.typedList, + }; +}; From b35df71f68db11fceb62278847bf3710badeb2d5 Mon Sep 17 00:00:00 2001 From: Katari Date: Sat, 14 Mar 2026 14:50:47 +0530 Subject: [PATCH 3/7] fixing code for some edge cases --- plugins/theme/helpers/index.mjs | 42 +++++++++++++++++++++++++------- plugins/theme/partials/index.mjs | 4 +-- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/plugins/theme/helpers/index.mjs b/plugins/theme/helpers/index.mjs index 9052684..a9a9687 100644 --- a/plugins/theme/helpers/index.mjs +++ b/plugins/theme/helpers/index.mjs @@ -65,15 +65,39 @@ export default (ctx) => ({ return null; }, - renderExamples(comment) { - if (!comment || !comment.blockTags) return ""; - const examples = comment.blockTags.filter((tag) => tag.tag === "@example"); + /** + * Renders `@example` tags from a comment as Markdown. + * Pass `headingLevel` to prepend a heading (block context); + * omit it for inline use (e.g. inside a list item). + * Always returns a string — never `null`. + * + * @param {import("typedoc").Comment | import("typedoc").CommentTag | null | undefined} comment + * @param {number} [headingLevel] + * @returns {string} + */ + renderExamples(comment, headingLevel) { + const examples = + comment?.blockTags?.filter((t) => t.tag === "@example") ?? []; if (!examples.length) return ""; - return ( - "\n\n" + - examples - .map((tag) => ctx.helpers.getCommentParts(tag.content).trim()) - .join("\n\n") - ); + + const bodies = examples + .map((tag) => { + const body = ctx.helpers.getCommentParts(tag.content).trim(); + if (!body) return null; // skip empty @example tags + + if (headingLevel != null) { + // Block context (signature / comment partial) → add heading + const prefix = "#".repeat(headingLevel + 1); + const suffix = + examples.length > 1 ? ` ${examples.indexOf(tag) + 1}` : ""; + return `${prefix} Example${suffix}\n\n${body}`; + } + + // Inline context (typedListItem) → no heading, just body + return body; + }) + .filter(Boolean); + + return bodies.length ? "\n\n" + bodies.join("\n\n") : ""; }, }); diff --git a/plugins/theme/partials/index.mjs b/plugins/theme/partials/index.mjs index 36b0f32..b8ca6de 100644 --- a/plugins/theme/partials/index.mjs +++ b/plugins/theme/partials/index.mjs @@ -37,7 +37,7 @@ export default (ctx) => { comment(model, options) { return ( baseComment.call(ctx, model, { ...options, showTags: false }) + - ctx.helpers.renderExamples(model) + ctx.helpers.renderExamples(model, options?.headingLevel) ); }, @@ -70,7 +70,7 @@ export default (ctx) => { headingLevel: options.headingLevel, showTags: false, }), - ctx.helpers.renderExamples(comment), + ctx.helpers.renderExamples(comment, options.headingLevel), ] .filter((x) => typeof x === "string" || Boolean(x)) .join("\n"); From eb8d2c43a215f2b0a43e5fa405aff8a119cedc1a Mon Sep 17 00:00:00 2001 From: Katari <143288488+Katari-8055@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:54:59 +0530 Subject: [PATCH 4/7] Update index.mjs --- plugins/theme/helpers/index.mjs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/theme/helpers/index.mjs b/plugins/theme/helpers/index.mjs index a9a9687..76c8bd7 100644 --- a/plugins/theme/helpers/index.mjs +++ b/plugins/theme/helpers/index.mjs @@ -69,7 +69,7 @@ export default (ctx) => ({ * Renders `@example` tags from a comment as Markdown. * Pass `headingLevel` to prepend a heading (block context); * omit it for inline use (e.g. inside a list item). - * Always returns a string — never `null`. + * Always returns a string never `null`. * * @param {import("typedoc").Comment | import("typedoc").CommentTag | null | undefined} comment * @param {number} [headingLevel] @@ -83,17 +83,15 @@ export default (ctx) => ({ const bodies = examples .map((tag) => { const body = ctx.helpers.getCommentParts(tag.content).trim(); - if (!body) return null; // skip empty @example tags + if (!body) return null; if (headingLevel != null) { - // Block context (signature / comment partial) → add heading const prefix = "#".repeat(headingLevel + 1); const suffix = examples.length > 1 ? ` ${examples.indexOf(tag) + 1}` : ""; return `${prefix} Example${suffix}\n\n${body}`; } - // Inline context (typedListItem) → no heading, just body return body; }) .filter(Boolean); From 3d31701c275bcb9c01f016b7c10dc103357aafdf Mon Sep 17 00:00:00 2001 From: Katari <143288488+Katari-8055@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:57:42 +0530 Subject: [PATCH 5/7] Update index.mjs --- plugins/theme/partials/index.mjs | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/plugins/theme/partials/index.mjs b/plugins/theme/partials/index.mjs index b8ca6de..83b7fa0 100644 --- a/plugins/theme/partials/index.mjs +++ b/plugins/theme/partials/index.mjs @@ -76,29 +76,29 @@ export default (ctx) => { .join("\n"); }, - memberTitle(model) { - const prefix = getMemberPrefix(model); - const params = model.signatures?.[0]?.parameters; + memberTitle(model) { + const prefix = getMemberPrefix(model); + const params = model.signatures?.[0]?.parameters; - if (!params) { - return `${prefix}\`${model.name}\``; - } + if (!params) { + return `${prefix}\`${model.name}\``; + } - const paramsString = params - .map((param, index) => { - const paramName = param.name; - if (param.flags?.isOptional) { - // For optional params, wrap comma + name in brackets (except for first param) - return index === 0 ? `[${paramName}]` : `[, ${paramName}]`; - } else { - // For required params, add comma separator (except for first param) - return index === 0 ? paramName : `, ${paramName}`; - } - }) - .join(""); + const paramsString = params + .map((param, index) => { + const paramName = param.name; + if (param.flags?.isOptional) { + // For optional params, wrap comma + name in brackets (except for first param) + return index === 0 ? `[${paramName}]` : `[, ${paramName}]`; + } else { + // For required params, add comma separator (except for first param) + return index === 0 ? paramName : `, ${paramName}`; + } + }) + .join(""); - return `${prefix}\`${model.name}(${paramsString})\``; - }, + return `${prefix}\`${model.name}(${paramsString})\``; + }, parametersList: ctx.helpers.typedList, typedParametersList: ctx.helpers.typedList, From 83127729c3c2bcfbcb69eda8bacc91aee3aeb5c4 Mon Sep 17 00:00:00 2001 From: Katari Date: Sat, 14 Mar 2026 15:04:23 +0530 Subject: [PATCH 6/7] fixing formate --- plugins/theme/helpers/index.mjs | 6 +----- plugins/theme/partials/index.mjs | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/plugins/theme/helpers/index.mjs b/plugins/theme/helpers/index.mjs index 76c8bd7..441ca1e 100644 --- a/plugins/theme/helpers/index.mjs +++ b/plugins/theme/helpers/index.mjs @@ -79,23 +79,19 @@ export default (ctx) => ({ const examples = comment?.blockTags?.filter((t) => t.tag === "@example") ?? []; if (!examples.length) return ""; - const bodies = examples .map((tag) => { const body = ctx.helpers.getCommentParts(tag.content).trim(); - if (!body) return null; - + if (!body) return null; if (headingLevel != null) { const prefix = "#".repeat(headingLevel + 1); const suffix = examples.length > 1 ? ` ${examples.indexOf(tag) + 1}` : ""; return `${prefix} Example${suffix}\n\n${body}`; } - return body; }) .filter(Boolean); - return bodies.length ? "\n\n" + bodies.join("\n\n") : ""; }, }); diff --git a/plugins/theme/partials/index.mjs b/plugins/theme/partials/index.mjs index 83b7fa0..54bd1ee 100644 --- a/plugins/theme/partials/index.mjs +++ b/plugins/theme/partials/index.mjs @@ -45,9 +45,7 @@ export default (ctx) => { const comment = options.multipleSignatures ? model.comment : model.comment || model.parent?.comment; - const stability = ctx.helpers.stabilityBlockquote(comment); - return [ stability, stability && "", From e658eabbc2b71242f5c22662e0d5f96d979166c4 Mon Sep 17 00:00:00 2001 From: Katari Date: Sat, 14 Mar 2026 15:14:27 +0530 Subject: [PATCH 7/7] chore: fix formatting issues --- plugins/theme/partials/index.mjs | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/plugins/theme/partials/index.mjs b/plugins/theme/partials/index.mjs index 54bd1ee..7bd48c6 100644 --- a/plugins/theme/partials/index.mjs +++ b/plugins/theme/partials/index.mjs @@ -74,29 +74,29 @@ export default (ctx) => { .join("\n"); }, - memberTitle(model) { - const prefix = getMemberPrefix(model); - const params = model.signatures?.[0]?.parameters; + memberTitle(model) { + const prefix = getMemberPrefix(model); + const params = model.signatures?.[0]?.parameters; - if (!params) { - return `${prefix}\`${model.name}\``; - } + if (!params) { + return `${prefix}\`${model.name}\``; + } - const paramsString = params - .map((param, index) => { - const paramName = param.name; - if (param.flags?.isOptional) { - // For optional params, wrap comma + name in brackets (except for first param) - return index === 0 ? `[${paramName}]` : `[, ${paramName}]`; - } else { - // For required params, add comma separator (except for first param) - return index === 0 ? paramName : `, ${paramName}`; - } - }) - .join(""); + const paramsString = params + .map((param, index) => { + const paramName = param.name; + if (param.flags?.isOptional) { + // For optional params, wrap comma + name in brackets (except for first param) + return index === 0 ? `[${paramName}]` : `[, ${paramName}]`; + } else { + // For required params, add comma separator (except for first param) + return index === 0 ? paramName : `, ${paramName}`; + } + }) + .join(""); - return `${prefix}\`${model.name}(${paramsString})\``; - }, + return `${prefix}\`${model.name}(${paramsString})\``; + }, parametersList: ctx.helpers.typedList, typedParametersList: ctx.helpers.typedList,