Сервисы Diplodoc

Статья создана
Обновлена 26 марта 2026 г.

Сервисы — это основные компоненты 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. Порядок выполнения хуков

Порядок выполнения хуков определяется двумя факторами:

  1. Жизненный цикл программы: основной порядок выполнения хуков определяется жизненным циклом Diplodoc.
  1. Конфигурация хуков: для управления порядком выполнения хуков с одинаковым именем используются возможности библиотеки tapable:
export class Extension {
    apply(program: Build) {
        getBaseHooks(program).BeforeAnyRun.tap({
            name: 'MyExtension',
            stage: 10, // Более высокий stage выполняется позже
            before: ['OtherExtension'], // Выполнить до указанных расширений
            after: ['AnotherExtension'], // Выполнить после указанных расширений
        }, (run) => {
            // Логика расширения
        });
    }
}

Также можно использовать различные типы хуков для специфических сценариев:

  • tap - синхронный хук
  • tapAsync - асинхронный хук с callback
  • tapPromise - асинхронный хук с Promise
  • intercept - для перехвата вызовов хука
Следующая