Работа с документацией
Как устроена документация
Документация состоит из двух частей:
- Руководство (
docs/guide/) — страницы, написанные вручную. Описывают концепции, паттерны и процессы. - API Reference (
docs/api/) — страницы, сгенерированные автоматически из JSDoc комментариев в исходном коде.
Технологии
- VitePress — генератор статического сайта на основе Vue и Vite
- vitepress-jsdoc — генерирует markdown-страницы из JSDoc комментариев (CLI mode)
- vitepress-sidebar — автоматически строит sidebar из файловой структуры
docs/api/
Структура файлов
docs/
├── .vitepress/
│ └── config.mjs # Конфиг VitePress (nav, sidebar, base URL)
├── index.md # Лендинг (hero + features)
├── guide/ # Вручную написанные страницы
│ ├── getting-started.md
│ ├── configuration.md
│ ├── services-overview.md
│ ├── dto-overview.md
│ ├── development.md
│ └── documentation.md
└── api/ # Автогенерация (в .gitignore!)
├── config.md
├── services/*.md
└── dto/ # генерируется scripts/dto-gen.cjs
├── <домен>.md # обзор категории
└── <домен>/<Тип>.md # страница на каждый DTOWARNING
Папка docs/api/ перегенерируется при каждом запуске docs:gen. Файлы, для которых исходник содержит тег @module, будут перезаписаны. Файлы без @module в исходнике защищены от перезаписи (см. Защита от перезаписи).
Скрипты
| Команда | Назначение |
|---|---|
npm run docs:dev | Локальная разработка с hot-reload (запускает VitePress dev-сервер и watcher JSDoc одновременно) |
npm run docs:gen | Генерация markdown из JSDoc + страниц DTO (без сборки сайта) |
npm run docs:build | Полная сборка: генерация + билд статического сайта в public/ |
npm run docs:preview | Предпросмотр собранного сайта |
npm run docs:backend-snapshot | Пересобирает scripts/backend-dto-snapshot.json из соседних бэкенд-репозиториев (Nuget.*ApiClient/Dto). Запускайте локально, когда меняются C#-DTO. |
Локальная разработка
npm run docs:devОткроется dev-сервер (обычно на http://localhost:5173). Изменения в guide-страницах и JSDoc комментариях подхватываются автоматически.
Редактирование руководства
Страницы руководства — обычные markdown-файлы в docs/guide/. Поддерживается весь синтаксис VitePress:
- Стандартный Markdown (заголовки, списки, таблицы, код)
- Контейнеры для заметок и предупреждений:md
::: tip Совет Текст подсказки ::: ::: warning Внимание Текст предупреждения ::: - Блоки кода с подсветкой синтаксиса и выделением строк
Добавление новой страницы
- Создайте файл
docs/guide/my-page.md - Добавьте запись в sidebar в
docs/.vitepress/config.mjs:jssidebar: { '/guide/': [ { text: 'Руководство', items: [ // ...существующие страницы { text: 'Моя страница', link: '/guide/my-page' }, ], }, ], }
Обновление API Reference
API Reference генерируется из JSDoc комментариев в исходном коде (src/). Чтобы обновить документацию API:
- Убедитесь, что в начале файла есть тег
@module(см. ниже) - Добавьте или обновите JSDoc комментарии в исходном файле
- Запустите
npm run docs:genилиnpm run docs:dev - Сгенерированный markdown появится в
docs/api/
Тег @module
Для того чтобы vitepress-jsdoc распознал файл и сгенерировал из него документацию, первой строкой файла должен быть тег @module:
/** @module clientService */
import { http } from '../http/httpClient'
class ClientService {
// ...
}Без этого тега vitepress-jsdoc пометит файл как EMPTY и создаст пустышку (только заголовок).
Когда добавлять @module
Добавляйте @module только в файлы, которые содержат JSDoc комментарии к методам/функциям. Если в файле нет JSDoc — тег @module не имеет смысла, и документацию для него нужно писать вручную в docs/api/.
Защита от перезаписи
Скрипт docs:gen использует wrapper (scripts/docs-gen.cjs), который защищает вручную написанные doc-файлы от перезаписи пустышками.
Логика работы:
- Перед запуском
vitepress-jsdocскрипт проверяет каждый исходный файл на наличие тега@module - Если
@moduleесть —vitepress-jsdocсгенерирует полноценную документацию, файл будет перезаписан - Если
@moduleнет, а doc-файл уже существует и содержит контент — файл сохраняется в памяти и восстанавливается после генерации
Это позволяет безопасно писать документацию вручную для файлов без JSDoc и не терять её при перегенерации.
Формат JSDoc
Для методов сервисов (классы TypeScript):
class MyService {
/**
* Описание метода
* @param {string} queryString - Готовая строка запроса
* @returns {Promise<ApiResult>} Ответ API
*/
async GetTable(queryString: string): Promise<ApiResult> { ... }
}Типы параметров берутся из сигнатуры TypeScript — дублировать их типами в @param не нужно, достаточно описания. Документация полей DTO генерируется отдельно из src/dto/ (см. DTO-документация).
JSDoc и парсер
Документация генерируется из .js, скомпилированного из TypeScript (tsc → .docs-build/), поэтому TS-синтаксис в исходниках поддерживается. Но в самих JSDoc-тегах @param/@returns избегайте сложных TS-выражений — описывайте тип словами или ссылайтесь на DTO.
Контейнеры VitePress в JSDoc
В описании метода можно использовать контейнеры VitePress (info, tip, warning, danger). Скрипт пост-обработки автоматически переносит их после секции «Возвращаемые данные» и перед «Пример».
Размещение — в блоке описания, до первого @-тега:
/**
* Описание метода
*
* ::: warning
* Текст предупреждения
* :::
*
* @param {string} queryString
* @returns {Promise<ApiResult>}
* @example
* // ...
*/Результат в документации:
Описание метода
#### Возвращаемые данные
**Returns**: ...
::: warning
Текст предупреждения
:::
#### Пример
...Не после @returns
Не размещайте контейнер после @returns — JSDoc-парсер захватит его в описание возвращаемого значения и он не дойдёт до нужного места.
Поддерживаемые теги
| Тег | Пример | Описание |
|---|---|---|
@module | @module clientService | Объявление модуля (обязательно для автогенерации) |
@param | @param {string} id | Параметр функции |
@returns | @returns {Object} | Возвращаемое значение |
@example | @example myFunc('test') | Пример использования |
@typedef | @typedef {Object} MyType | Определение типа |
@deprecated | @deprecated Используйте newFunc | Устаревший метод |
@alias | @alias module:clientService | Привязка класса к модулю (см. ниже) |
@private | @private | Приватный метод (исключается из документации) |
@alias и классы
Тег @module объявляет модуль, но JSDoc-парсер не привязывает к нему методы ES6-классов автоматически. Чтобы методы класса отображались в документации как методы модуля, перед классом нужно добавить @alias:
/** @module clientService */
import { http } from '../http/httpClient'
/** @alias module:clientService */
class ClientService {
/**
* Получает данные клиента по ID
* @param {number} id - ID клиента
* @returns {Promise<ApiResult>} Данные клиента
*/
async GetById(id: number): Promise<ApiResult> { ... }
}
export const clientService = new ClientService()Без @alias: парсер не свяжет GetById с модулем clientService. В документации появится страница модуля, но без методов.
С @alias module:clientService: парсер поймёт, что методы ClientService принадлежат модулю clientService, и отобразит их на странице модуля.
Правило
Каждый сервис-класс должен иметь @alias module:<имяМодуля> перед объявлением класса, где <имяМодуля> совпадает с @module в начале файла.
DTO-документация
Страницы docs/api/dto/<категория>.md генерируются автоматически скриптом scripts/dto-gen.cjs из TS-источников в src/dto/<категория>/. На каждую категорию — одна страница с таблицей полей, типов, обязательности, описания (из JSDoc) и пример JSON.
Обогащение бэкенд-snapshot
Скрипт scripts/dto-backend-snapshot.cjs проходит по соседним репозиториям сервисов (Nuget.*ApiClient/Dto), парсит C#-классы/enum/record и записывает результат в scripts/backend-dto-snapshot.json. Этот файл закоммичен — CI на GitLab Pages не имеет доступа к соседним репам, поэтому snapshot должен быть актуальным в репозитории.
Что попадает в snapshot:
- Классы и records — список свойств с типами и текстом из
/// <summary>. - Enum'ы — все значения (с явными числами или вычисленными по порядку) и описания.
- Путь до файла — относительно корня монорепы (используется как ссылка-источник в документации).
- Сервис — имя соседнего репозитория, в котором найден тип.
В сгенерированной документации это отображается так:
- Заголовок DTO дополняется строкой
Backend-источник: <путь> (<сервис>). - В таблицу полей добавляется колонка
Тип (C#)рядом с TypeScript-типом. - Описание поля берётся из JSDoc TS-исходника, а если его нет — из
/// <summary>бэкенда. - В таблицу enum-значений добавляется колонка
Код (C#)с числовым значением из C#. - В оглавлении категории рядом с типом ставится маркер
· backend ✓для типов, у которых нашёлся бэкенд-источник.
Когда обновлять snapshot
Запускайте npm run docs:backend-snapshot локально перед коммитом, если:
- В бэкенд-сервисе добавлен/переименован/удалён DTO или enum.
- Изменены поля в существующем DTO (тип, имя, XML-doc).
- Добавлен новый сервис с публичным
Nuget.*ApiClient.
Затем npm run docs:gen соберёт документацию с обновлёнными данными.
Без бэкенд-репов
Если запустить dto-gen.cjs без backend-dto-snapshot.json (например, в чистом окружении), генерация не упадёт — просто не будет колонок и строк с C#-данными. В консоли появится (snapshot бэкенда не найден — обогащения нет).
Деплой
Документация автоматически собирается и публикуется на GitLab Pages при пуше в ветку develop.
Pipeline определён в .gitlab-ci.yml:
npm ci— установка зависимостейnpm run docs:build— генерация JSDoc markdown + сборка VitePress- Артефакт
public/публикуется как GitLab Pages
Доступ к документации ограничен участниками проекта (настройка в GitLab: Settings → General → Pages → "Only project members").
Конфигурация VitePress
Основной конфиг: docs/.vitepress/config.mjs
Ключевые параметры:
| Параметр | Значение | Описание |
|---|---|---|
base | '/frontend.npm.serviceslibrary/' | Базовый путь URL на GitLab Pages |
outDir | '../public' | Директория билда (для GitLab Pages) |
lang | 'ru-RU' | Язык сайта |
search.provider | 'local' | Встроенный полнотекстовый поиск |