Сервисы Diplodoc
Сервисы — это основные компоненты Diplodoc, отвечающие за различные аспекты обработки документации. Каждый сервис предоставляет свой набор хуков для расширения функциональности.
Доступные сервисы
- TOC Service — управление структурой документации.
- Leading Service — обработка разводящих страниц.
- Markdown Service — трансформация markdown-контента.
- Meta Service — работа с метаданными документации.
- Vars Service — управление переменными и шаблонами.
- VCS Service — работа с системой контроля версий.
- Search Service — организация поиска по документации.
- Logger Service — управление логгированием.
Работа с сервисами
Получение доступа к сервисам
Все сервисы доступны через контекст выполнения run, который передается в хуки:
export class Extension {
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap('MyExtension', (run) => {
// Доступ к сервисам
const {toc, markdown, leading} = run;
});
}
}
Получение хуков сервиса
Для работы с сервисом нужно получить его хуки с помощью соответствующей функции:
import {getHooks as getBaseHooks} from '@diplodoc/cli/lib/program';
import {getHooks as getTocHooks} from '@diplodoc/cli/lib/toc';
import {getHooks as getMarkdownHooks} from '@diplodoc/cli/lib/markdown';
import {getHooks as getLeadingHooks} from '@diplodoc/cli/lib/leading';
export class Extension {
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap('MyExtension', (run) => {
// Получение хуков сервисов
const tocHooks = getTocHooks(run.toc);
const markdownHooks = getMarkdownHooks(run.markdown);
const leadingHooks = getLeadingHooks(run.leading);
});
}
}
Использование хуков
Хуки сервисов следуют единому паттерну использования:
serviceHooks.HookName.tap('ExtensionName', (data) => {
// Синхронная обработка
return modifiedData;
});
// или
serviceHooks.HookName.tapPromise('ExtensionName', async (data) => {
// Асинхронная обработка
return modifiedData;
});
API сервисов
Каждый сервис, помимо хуков, предоставляет набор методов для работы с данными:
export class Extension {
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap('MyExtension', (run) => {
// TOC Service API
const tocPath = run.toc.dir(entry); // Получение директории TOC
const tocData = run.toc.data(entry); // Получение данных TOC
const entries = run.toc.entries; // Список всех entry в TOC
// Leading Service API
const hasLeading = run.leading.has(path); // Проверка наличия leading-страницы
const leadingData = run.leading.get(path); // Получение данных leading-страницы
// Markdown Service API
const content = run.markdown.read(path); // Чтение markdown-файла
await run.markdown.save(path, content); // Сохранение markdown-файла
});
}
}
Использование API сервисов вместо прямой работы с файловой системой позволяет:
- Получать данные в правильном контексте сборки
- Использовать внутреннее кеширование
- Поддерживать различные форматы и источники данных
- Обеспечивать консистентность данных
Лучшие практики
1. Изоляция логики
Разделяйте логику обработки по соответствующим сервисам:
export class Extension {
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap('MyExtension', (run) => {
// TOC-специфичная логика
const tocHooks = getTocHooks(run.toc);
tocHooks.Item.tap('MyExtension', (item) => {
// Работа со структурой
return item;
});
// Markdown-специфичная логика
const markdownHooks = getMarkdownHooks(run.markdown);
markdownHooks.Resolved.tap('MyExtension', (content) => {
// Работа с контентом
return content;
});
});
}
}
2. Обработка ошибок
Всегда обрабатывайте возможные ошибки в хуках:
export class Extension {
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap('MyExtension', (run) => {
const tocHooks = getTocHooks(run.toc);
tocHooks.Item.tapPromise('MyExtension', async (item) => {
try {
const processedItem = await processItem(item);
return processedItem;
} catch (error) {
run.logger.error('Failed to process TOC item:', error);
return item;
}
});
});
}
}
3. Порядок выполнения хуков
Порядок выполнения хуков определяется двумя факторами:
- Жизненный цикл программы: основной порядок выполнения хуков определяется жизненным циклом Diplodoc.
- Конфигурация хуков: для управления порядком выполнения хуков с одинаковым именем используются возможности библиотеки tapable:
export class Extension {
apply(program: Build) {
getBaseHooks(program).BeforeAnyRun.tap({
name: 'MyExtension',
stage: 10, // Более высокий stage выполняется позже
before: ['OtherExtension'], // Выполнить до указанных расширений
after: ['AnotherExtension'], // Выполнить после указанных расширений
}, (run) => {
// Логика расширения
});
}
}
Также можно использовать различные типы хуков для специфических сценариев:
tap- синхронный хукtapAsync- асинхронный хук с callbacktapPromise- асинхронный хук с Promiseintercept- для перехвата вызовов хука