Skip to content

Commit 7b71ba5

Browse files
committed
implement configurable markdown templates
1 parent 7e0e85a commit 7b71ba5

File tree

4 files changed

+55
-9
lines changed

4 files changed

+55
-9
lines changed

src/application/Apexdocs.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
import { resolveAndValidateSourceDirectories } from '#utils/source-directory-resolver';
2020
import { ReflectionError, ReflectionErrors, HookError } from '../core/errors/errors';
2121
import { FileReadingError, FileWritingError } from './errors';
22+
import * as path from 'path';
2223

2324
/**
2425
* Application entry-point to generate documentation out of Apex source files.
@@ -29,6 +30,18 @@ export class Apexdocs {
2930
*/
3031
static async generate(config: UserDefinedConfig, logger: Logger): Promise<E.Either<unknown[], string>> {
3132
logger.logSingle(`Generating ${config.targetGenerator} documentation...`);
33+
34+
// Set custom template directory if provided (only for configs that support it)
35+
if (
36+
(config.targetGenerator === 'markdown' || config.targetGenerator === 'changelog') &&
37+
typeof (config as UserDefinedMarkdownConfig).customTemplateDir === 'string' &&
38+
(config as UserDefinedMarkdownConfig).customTemplateDir
39+
) {
40+
const { Template } = await import('../core/template');
41+
const dir = (config as UserDefinedMarkdownConfig).customTemplateDir!;
42+
const absDir = path.isAbsolute(dir) ? dir : path.resolve(process.cwd(), dir);
43+
Template.setCustomTemplateDir(absDir);
44+
}
3245

3346
try {
3447
switch (config.targetGenerator) {

src/cli/commands/markdown.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,8 @@ export const markdownOptions: Record<keyof CliConfigurableMarkdownConfig, Option
119119
type: 'boolean',
120120
describe: 'Whether to include the inline help text for fields in the generated files.',
121121
},
122+
customTemplateDir: {
123+
type: 'string',
124+
describe: 'Directory where custom template overrides are stored.',
125+
},
122126
};

src/core/shared/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type CliConfigurableMarkdownConfig = {
4545
referenceGuideTitle: string;
4646
includeFieldSecurityMetadata: boolean;
4747
includeInlineHelpTextMetadata: boolean;
48+
customTemplateDir?: string; // Optional directory for custom templates
4849
};
4950

5051
export type UserDefinedMarkdownConfig = {

src/core/template.ts

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { fieldsPartialTemplate } from './markdown/templates/fieldsPartialTemplat
1010
import { classMarkdownTemplate } from './markdown/templates/class-template';
1111
import { enumMarkdownTemplate } from './markdown/templates/enum-template';
1212
import { interfaceMarkdownTemplate } from './markdown/templates/interface-template';
13+
import * as fs from 'fs';
14+
import * as path from 'path';
1315

1416
export type CompilationRequest = {
1517
template: string;
@@ -18,17 +20,43 @@ export type CompilationRequest = {
1820

1921
export class Template {
2022
private static instance: Template;
23+
private static customTemplateDir: string | undefined;
24+
25+
/**
26+
* Set the custom template directory to use for overrides.
27+
* Should be called before getInstance().
28+
*/
29+
public static setCustomTemplateDir(dir: string) {
30+
Template.customTemplateDir = dir;
31+
}
2132

2233
private constructor() {
23-
Handlebars.registerPartial('typeDocumentation', typeDocPartial);
24-
Handlebars.registerPartial('documentablePartialTemplate', documentablePartialTemplate);
25-
Handlebars.registerPartial('methodsPartialTemplate', methodsPartialTemplate);
26-
Handlebars.registerPartial('constructorsPartialTemplate', constructorsPartialTemplate);
27-
Handlebars.registerPartial('groupedMembersPartialTemplate', groupedMembersPartialTemplate);
28-
Handlebars.registerPartial('fieldsPartialTemplate', fieldsPartialTemplate);
29-
Handlebars.registerPartial('classTemplate', classMarkdownTemplate);
30-
Handlebars.registerPartial('enumTemplate', enumMarkdownTemplate);
31-
Handlebars.registerPartial('interfaceTemplate', interfaceMarkdownTemplate);
34+
// Template name to default value mapping
35+
const templates: Record<string, string> = {
36+
typeDocumentation: typeDocPartial,
37+
documentablePartialTemplate: documentablePartialTemplate,
38+
methodsPartialTemplate: methodsPartialTemplate,
39+
constructorsPartialTemplate: constructorsPartialTemplate,
40+
groupedMembersPartialTemplate: groupedMembersPartialTemplate,
41+
fieldsPartialTemplate: fieldsPartialTemplate,
42+
classTemplate: classMarkdownTemplate,
43+
enumTemplate: enumMarkdownTemplate,
44+
interfaceTemplate: interfaceMarkdownTemplate,
45+
};
46+
47+
// If customTemplateDir is set, try to load each template from it
48+
for (const [name, defaultValue] of Object.entries(templates)) {
49+
let value = defaultValue;
50+
if (Template.customTemplateDir) {
51+
const customPath = path.join(Template.customTemplateDir, `${name}.hbs`);
52+
53+
if (fs.existsSync(customPath)) {
54+
value = fs.readFileSync(customPath, 'utf8');
55+
}
56+
}
57+
58+
Handlebars.registerPartial(name, value);
59+
}
3260

3361
Handlebars.registerHelper('link', link);
3462
Handlebars.registerHelper('code', convertCodeBlock);

0 commit comments

Comments
 (0)