Diplodoc Extensions API
The Diplodoc Extensions API provides a mechanism for extending the functionality of the Diplodoc CLI. Built on a hook-based system using the tappable library, it allows creating modular, integrable, and extensible components.
The CLI's internal modules are built on the Extensions API architecture.
Features
- Hook-based Architecture: A hook system for extending functionality at various stages of the documentation build process.
- Type Safety: Full TypeScript support with detailed type definitions.
- Modular Design: Creation of independent, reusable extensions.
- Configuration Support: Flexible configuration via configuration files and command-line parameters.
- Resource Management: Built-in lifecycle hooks for proper initialization and cleanup of resources.
- Logging and Debugging: Integrated logging system with multiple levels of detail.
Basic Concepts
Program and Run
At the core of the Diplodoc architecture are two key classes:
-
Program — the base class for all CLI commands. It provides:
- A hook system for extending functionality
- Configuration management
- Access to logging
- An interface for registering extensions
-
Run — the command execution context. It contains:
- Access to services (TOC, Markdown, Leading, etc.)
- Information about the current state
- Utilities for working with files
- Logging and debugging systems
Hooks and Their Usage
Hooks are the primary mechanism for extending functionality. They allow you to:
- Integrate into various stages of program execution
- Modify service behavior
- Add new functionality
There are two types of hooks:
-
Base Hooks — common program hooks:
export class Extension { apply(program: Build) { // Получение базовых hooks const baseHooks = getBaseHooks(program); // Hook перед любым запуском baseHooks.BeforeAnyRun.tap('MyExtension', (run) => { // Инициализация }); // Hook после выполнения baseHooks.AfterAnyRun.tap('MyExtension', (run) => { // Очистка }); } } -
Service Hooks — specific to each service:
export class Extension { apply(program: Build) { getBaseHooks(program).BeforeAnyRun.tap('MyExtension', (run) => { // Получение hooks конкретного сервиса const tocHooks = getTocHooks(run.toc); const markdownHooks = getMarkdownHooks(run.markdown); const leadingHooks = getLeadingHooks(run.leading); // Использование hooks tocHooks.Item.tap('MyExtension', (item) => { // Обработка элемента TOC }); }); } }
Working with Services
Services are the main components of Diplodoc, responsible for various aspects of documentation processing.
Access to services is provided through the run context:
export class Extension {
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap('MyExtension', (run) => {
// Доступ к сервисам
const {toc, markdown, leading, meta, vars} = run;
// Получение hooks сервисов
const tocHooks = getTocHooks(toc);
const markdownHooks = getMarkdownHooks(markdown);
const leadingHooks = getLeadingHooks(leading);
const metaHooks = getMetaHooks(meta);
const varsHooks = getVarsHooks(vars);
});
}
}
Detailed description of each service:
- TOC Service — managing the documentation structure.
- Leading Service — processing leading pages.
- Markdown Service — transforming markdown content.
- Meta Service — working with documentation metadata.
- Vars Service — managing variables and templates.
- VCS Service — working with a version control system.
- Search Service — organizing documentation search.
- Logger Service — managing logging.
When to use extensions
Extensions are especially useful when you need to:
- Add new command-line parameters to the Diplodoc CLI.
- Modify or improve the documentation build process.
- Add support for new file types or processing methods.
- Integrate with external services or APIs.
- Add custom validation or document transformation steps.
Types of extensions
Diplodoc supports several types of extensions, each designed to solve specific tasks:
1. Command Extensions
This type of extension allows you to modify the Diplodoc CLI interface. Use it when you need to:
- add new commands to the CLI,
- extend existing commands with new parameters,
- change the behavior of existing commands.
The example below shows how to add a new parameter to a command:
Example of adding a new parameter to a command"
import {Build} from '@diplodoc/cli';
export class Extension {
apply(program) {
if (Build.is(program)) {
getBaseHooks(program).Command.tap('MyCommand', (command) => {
command.addOption(new Option('--my-option'));
});
}
}
}
2. Processing Extensions
Processing Extensions are designed to modify the documentation build process. They are especially useful when you need to:
- change the content or structure of the TOC,
- transform markdown content,
- add custom includers,
- perform content validation during the build.
Example extension"
export class Extension {
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap('MyProcessor', (run) => {
// Получение hooks нужных сервисов
const tocHooks = getTocHooks(run.toc);
const markdownHooks = getMarkdownHooks(run.markdown);
// Настройка обработки
tocHooks.Item.tapPromise('MyProcessor', async (item) => {
// Обработка элемента TOC
return item;
});
markdownHooks.Resolved.tapPromise('MyProcessor', async (content) => {
// Обработка markdown
return content;
});
});
}
}
3. Integration Extensions
Integration Extensions enable Diplodoc to interact with external services. Use them for:
- loading data from external APIs,
- enriching documentation with external metadata,
- synchronizing with other systems,
- sending notifications or metrics.
Example extension:
export class Extension {
constructor(private apiKey: string) {}
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap('MyIntegration', (run) => {
// Интеграция с внешним API
getLeadingHooks(run.leading).Resolved.tapPromise('MyIntegration', async (content) => {
const externalData = await this.fetchExternalData(this.apiKey);
return {
...content,
externalData
};
});
});
}
private async fetchExternalData(apiKey: string) {
// Логика получения данных из внешнего API
}
}