Skip to content

Commit

Permalink
chore(core): expose dedicated async jobs to renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
tgreyuk committed Jan 1, 2025
1 parent c8939fc commit c317a99
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 134 deletions.
72 changes: 14 additions & 58 deletions packages/typedoc-plugin-markdown/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,16 @@
*
* @module core
*/
import { getTranslatable } from '@plugin/internationalization/translatable.js';
import { setupInternationalization } from '@plugin/internationalization/index.js';
import { declarations } from '@plugin/options/index.js';
import { resolvePackages } from '@plugin/renderer/packages.js';
import { MarkdownRendererHooks, MarkdownTheme } from 'public-api.js';
import { render, setupRenderer } from '@plugin/renderer/index.js';
import { MarkdownRenderer } from '@plugin/types/index.js';
import {
Application,
Context,
Converter,
DeclarationOption,
EventHooks,
ParameterHint,
ParameterType,
} from 'typedoc';
import { render } from './renderer/render.js';

/**
* The function that is called by TypeDoc to bootstrap the plugin.
Expand All @@ -27,13 +23,6 @@ import { render } from './renderer/render.js';
*
* This method is not intended to be consumed in any other context that via the `plugin` option.
*
* The load functions:
*
* 1. Bootstrap the plugin options
* 2. Configures markdown outputs
* 3. Configures localization
* 4. Applies any other behaviour
*
* The module also exports anything that is available publicly.
*
*/
Expand All @@ -43,22 +32,13 @@ export function load(app: Application) {
* 1. Bootstrap options
* ====================
*/

// Iterate over declaration definitions and to the container.
Object.entries(declarations).forEach(([name, declaration]) => {
app.options.addDeclaration({
name,
...declaration,
} as DeclarationOption);
});

app.renderer.defineTheme('markdown', MarkdownTheme);

/**
* =============================
* 2. Configure markdown outputs
* =============================
*/
app.options.addDeclaration({
name: 'markdown',
outputShortcut: 'markdown',
Expand All @@ -68,48 +48,24 @@ export function load(app: Application) {
defaultValue: './docs',
});

app.outputs.addOutput('markdown', async (out, project) => {
await render(app.renderer, project, out);
});

app.outputs.setDefaultOutputName('markdown');

Object.defineProperty(app.renderer, 'markdownHooks', {
value: new EventHooks<MarkdownRendererHooks, string>(),
});

/**
* =========================
* 3. Configure localization
* =========================
* =============================
* 2. Configure markdown outputs
* =============================
*/

// Load the additional translations used by the theme for the selected language.
app.converter.on(Converter.EVENT_BEGIN, () => {
app.internationalization.addTranslations(
app.options.getValue('lang'),
{ ...getTranslatable(app) },
true,
);
app.outputs.addOutput('markdown', async (out, project) => {
await render(app.renderer as unknown as MarkdownRenderer, project, out);
});

/**
* ============================
* 4. Apply any other behaviour
* ============================
*/
app.outputs.setDefaultOutputName('markdown');

/**
* Currently options set for packages are only stored on the converter and are destroyed before being passed to the {@link Renderer}.
*
* By intercepting the package options set in the converter and storing them on the renderer we can use them later in the theme.
*
* =====================================
* 3. Setup up renderer and translations
* ======================================
*/
app.converter.on(Converter.EVENT_RESOLVE_END, (context: Context) => {
if (app.options.packageDir) {
resolvePackages(app, context, app.options.packageDir);
}
});
setupRenderer(app);
setupInternationalization(app);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
* @module
*/
export * from './locales/index.js';
export * from './translatable.js';
export * from './setup.js';
35 changes: 35 additions & 0 deletions packages/typedoc-plugin-markdown/src/internationalization/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { en, jp, ko, zh } from '@plugin/internationalization/index.js';
import { Application, Converter } from 'typedoc';

export function setupInternationalization(app: Application): void {
app.converter.on(Converter.EVENT_BEGIN, () => {
app.internationalization.addTranslations(
app.options.getValue('lang'),
{ ...getTranslatable(app) },
true,
);
});
}

/**
* Returns subset of translatable strings for the plugin.
*
* These will then be merged with the main set of TypeDoc string.
*
* @category Functions
*/
function getTranslatable(app: Application) {
const LOCALES = {
en,
jp,
ko,
zh,
};
return {
...LOCALES['en'],
...(app.lang !== 'en' && Object.keys(LOCALES).includes(app.lang)
? { ...LOCALES[app.lang] }
: {}),
...app.options.getValue('locales')[app.lang],
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,3 @@
*
* @module
*/
import { en, jp, ko, zh } from 'internationalization/index.js';
import { Application } from 'typedoc';

/**
* Returns subset of translatable strings for the plugin.
*
* These will then be merged with the main set of TypeDoc string.
*
* @category Functions
*/
export function getTranslatable(app: Application) {
const LOCALES = {
en,
jp,
ko,
zh,
};
return {
...LOCALES['en'],
...(app.lang !== 'en' && Object.keys(LOCALES).includes(app.lang)
? { ...LOCALES[app.lang] }
: {}),
...app.options.getValue('locales')[app.lang],
};
}
2 changes: 1 addition & 1 deletion packages/typedoc-plugin-markdown/src/renderer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
* @module
*/

export * from './packages.js';
export * from './render.js';
export * from './setup.js';
37 changes: 0 additions & 37 deletions packages/typedoc-plugin-markdown/src/renderer/packages.ts

This file was deleted.

11 changes: 7 additions & 4 deletions packages/typedoc-plugin-markdown/src/renderer/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {
MarkdownPageEvent,
MarkdownRendererEvent,
} from '@plugin/events/index.js';
import { MarkdownTheme } from '@plugin/public-api.js';
import { MarkdownTheme } from '@plugin/theme/index.js';
import { MarkdownRenderer } from '@plugin/types/index.js';
import * as fs from 'fs';
import * as path from 'path';
import {
Expand All @@ -24,7 +25,7 @@ import {
* - Adds any logic specific to markdown rendering.
*/
export async function render(
renderer: Renderer,
renderer: MarkdownRenderer,
project: ProjectReflection,
outputDirectory: string,
) {
Expand All @@ -49,13 +50,15 @@ export async function render(

renderer.trigger(MarkdownRendererEvent.BEGIN, output);

await executeJobs(renderer.preRenderAsyncJobs, output);
await executeJobs(renderer.preMarkdownRenderAsyncJobs, output);
await executeJobs(renderer.preRenderAsyncJobs, output); // for backward compatibility

await renderPages(renderer, output);

copyMediaFiles(project, outputDirectory);

await executeJobs(renderer.postRenderAsyncJobs, output);
await executeJobs(renderer.postMarkdownRenderAsyncJobs, output);
await executeJobs(renderer.postRenderAsyncJobs, output); // for backward compatibility

renderer.trigger(MarkdownRendererEvent.END, output);

Expand Down
66 changes: 66 additions & 0 deletions packages/typedoc-plugin-markdown/src/renderer/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { MarkdownTheme } from '@plugin/theme/index.js';
import {
MarkdownRenderer,
MarkdownRendererHooks,
} from '@plugin/types/index.js';
import * as fs from 'fs';
import * as path from 'path';
import { Application, Context, Converter, EventHooks } from 'typedoc';

/**
* Create dedicated hooks and async job collections for markdown rendering.
*/
export function setupRenderer(app: Application) {
app.renderer.defineTheme('markdown', MarkdownTheme);

Object.defineProperty(app.renderer, 'markdownHooks', {
value: new EventHooks<MarkdownRendererHooks, string>(),
});

Object.defineProperty(app.renderer, 'preMarkdownRenderAsyncJobs', {
value: [],
});

Object.defineProperty(app.renderer, 'postMarkdownRenderAsyncJobs', {
value: [],
});

app.converter.on(Converter.EVENT_RESOLVE_END, (context: Context) => {
if (app.options.packageDir) {
resolvePackages(app, context, app.options.packageDir);
}
});
}

/**
* Resolves packages meta data for the project.
*
* @remarks
*
* Currently options set for packages are only stored on the converter and are destroyed before being passed to the Renderer.
*
* By intercepting the package options set in the converter and storing them on the renderer we can use them later in the theme.
*/
function resolvePackages(
app: Application,
context: Context,
packageDir: string,
) {
const packageJsonContents = fs
.readFileSync(path.join(packageDir, 'package.json'))
.toString();

const packageJson = packageJsonContents
? JSON.parse(packageJsonContents)
: {};

const renderer = app.renderer as unknown as MarkdownRenderer;

renderer.packagesMeta = {
...(renderer.packagesMeta || {}),
[context.project.name]: {
description: packageJson.description,
options: app.options,
},
};
}
5 changes: 0 additions & 5 deletions packages/typedoc-plugin-markdown/src/theme/markdown-theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
ProjectReflection,
Reflection,
ReflectionKind,
Renderer,
Theme,
} from 'typedoc';

Expand All @@ -24,10 +23,6 @@ import {
* The API follows the implementation of [TypeDoc's custom theming](/~https://github.com/TypeStrong/typedoc/blob/master/internal-docs/custom-themes.md) with some minor adjustments.
*/
export class MarkdownTheme extends Theme {
constructor(renderer: Renderer) {
super(renderer);
}

/**
* Renders a template and page model to a string.
*/
Expand Down
Loading

0 comments on commit c317a99

Please sign in to comment.