@tp-prepare/vitepress-module-graph
v0.3.0
Published
Плагин VitePress: граф модулей и треков, CLI module-graph
Readme
@tp-prepare/vitepress-module-graph
Граф учебного модуля «люди — треки — подзадачи» для сайта на VitePress: страница модуля с графом и фильтрами, шапка на странице каждого трека, архив модулей, меню раздела и прогресс треков по задачам доски GitHub Projects. Данные — папка с файлами Markdown и YAML; ошибка в данных роняет сборку и называет файл и поле.
Так это выглядит на сайте команды Cringe Driven Development: модуль №2.
Нужны VitePress 1.6+ и Vue 3.5+, CLI работает под Node 22+ и bun.
npm install @tp-prepare/vitepress-module-graph| Вход | Что внутри |
|---|---|
| @tp-prepare/vitepress-module-graph | модель: типы, настройки по умолчанию, разбор треков и людей, правила, связи графа, фильтры, разбор снимка доски |
| …/node | loadModuleDir, readModules, moduleSidebar, createModulesLoader — для конфига и загрузчика VitePress |
| …/theme | installModuleGraph(app, data) (регистрирует глобально компоненты <ModuleGraph/> и <ModuleList/>), trackHeader (шапка трека), useModuleGraph() |
| …/style.css | цвета направлений по умолчанию (переменные --mg-area-*) |
| module-graph | CLI: проверка папки модулей и доска GitHub |
Подключение
Три файла сайта:
// site/modules/modules.data.ts — папка этого файла и есть папка модулей
import { createModulesLoader } from '@tp-prepare/vitepress-module-graph/node';
export default createModulesLoader(import.meta.url);// site/.vitepress/config.mts
import { moduleSidebar, readModules } from '@tp-prepare/vitepress-module-graph/node';
// themeConfig.sidebar — модули по возрастанию номера, каждый сворачивается стрелкой:
'/modules/': moduleSidebar(readModules('site/modules')),
// пакет отдаёт .vue как есть — Vite сайта должен собрать его и для SSR:
vite: { ssr: { noExternal: ['@tp-prepare/vitepress-module-graph'] } },// site/.vitepress/theme/index.ts
import { installModuleGraph, trackHeader } from '@tp-prepare/vitepress-module-graph/theme';
import '@tp-prepare/vitepress-module-graph/style.css';
import { data } from '../../modules/modules.data';
// Layout: () => h(DefaultTheme.Layout, null, { 'doc-before': trackHeader }),
// enhanceApp({ app }) { installModuleGraph(app, data) } — <ModuleGraph/>, <ModuleList/> и provide данныхБез
vite.ssr.noExternalсборка падает сUnknown file extension ".vue": Vite оставляет пакет изnode_modulesвнешним для SSR, а Node не умеет загружать.vue.createModulesLoader(url)возвращает{ watch, load }загрузчика VitePress;watch—index.mdмодулей, файлы треков,people.yaml,module-graph.yaml,board.json.data— это подстановка VitePress. Если сайт проверяет типы (tsc), объявите её вmodules.data.ts:import type { ModuleGraphData } from '@tp-prepare/vitepress-module-graph'; declare const data: ModuleGraphData; export { data };trackHeader— шапка трека для слотаdoc-before: на странице не трека ничего не рисует.Компоненты берут данные через
provide/inject:useModuleGraph()внеinstallModuleGraphбросаетmodule-graph: вызовите installModuleGraph(app, data) в enhanceApp.Цвета
--mg-area-<ключ>изmodule-graph.yamlрисует<style>в корне графа, архива и шапки трека::where(:root)и:where(html.dark), то есть с нулевой специфичностью — сайт переопределяет их обычным:root { … }.style.cssдаёт те же переменные для направлений по умолчанию.
Страницы: <папка модулей>/index.md с <ModuleList /> — архив модулей, <номер>/index.md с <ModuleGraph /> —
граф модуля, страница трека — сам файл трека.
Папка модулей
<папка модулей>/ по умолчанию site/modules
index.md страница архива (<ModuleList/>)
module-graph.yaml настройки, необязательный
people.yaml люди, обязательный
board.json снимок доски, необязательный
<номер>/index.md модуль: title, sprints, <ModuleGraph/>
<номер>/tracks/<id>.md трекОшибки — одной строкой: <файл от родителя папки модулей>: <поле> — <что не так>, например
modules/people.yaml: [2].area — неизвестное направление qa; допустимо: front, back, devops, fullstack, team.
Сломанный YAML и frontmatter — с файлом и строкой, без стека.
module-graph.yaml
Необязательный. Без него действуют значения ниже, кроме раздела board — по умолчанию его нет.
route: /modules/
areas: # порядок = порядок в фильтре и легенде
front: { label: Фронт, color: "#2c6bd4", dark: "#5f95f1" }
back: { label: Бэк, color: "#13886b", dark: "#3fbc9c" }
devops: { label: DevOps, color: "#b07710", dark: "#e1a740" }
fullstack: { label: Фронт + бэк, color: "#c9445a", dark: "#e47584", needs: [front, back] }
team: { label: Инструменты команды, color: "#6b7c1c", dark: "#a9ba5c" }
sides: { front: фронт, back: бэк, devops: devops, team: команда }
sprint: "Sprint {n}"
board: { owner: Cringe-Driven-Development-Team, project: 1, field: Трек }route— адрес папки модулей на сайте, с/в начале и в конце; от него строятся ссылки на модули, треки и подстраницы.areas(направления треков) иsides(стороны исполнителей), если заданы, заменяют значения по умолчанию целиком. Ключи — строчная латиница, цифры и дефис, первая — буква.color(светлая тема) иdark(тёмная) —#rrggbb.needs— стороны изsides: у трека с этим направлением исполнители (вместе с исполнителями подтреков) закрывают все перечисленные стороны.sprint— шаблон названия спринта с одним{n},n— целое число.board.owner— организация или пользователь GitHub,board.project— номер проекта,board.field— имя поля доски с одиночным выбором, в котором задача выбирает трек.- Неизвестный ключ на любом уровне — ошибка: опечатка не откатывается молча на значение по умолчанию.
people.yaml
- login: YarikMix
name: Ярослав
role: ментор фронта
area: front
mentor: trueСписок, порядок — порядок на графе. login (логин GitHub), name, role, area — непустые строки, area —
ключ из areas, mentor — только true. Логины не повторяются.
Модуль
Каталог <номер>/ (2, 3, …) с index.md: во frontmatter title, необязательные period и sprints
(спринты модуля по шаблону sprint, например sprints: [Sprint 5, Sprint 6] — по ним задача доски попадает в
модуль), aside: false; в тексте <ModuleGraph />.
Трек
Файл <номер>/tracks/<id>.md, id — строчная латиница, цифры и дефис:
---
title: Multi-branch деплой фронта и стейджинг бэка через Coolify
label: Multi-branch + стейджинг (Coolify) # подпись на графе; без него — title
area: devops # ключ из areas
do: # логин → сторона из sides
iRedTea: devops
mentors: [YarikMix, blackHATred] # необязательно; только люди с mentor: true в people.yaml
subtasks: # необязательно: строка или { title, issues, subtasks }
- Откаты
- title: Стейджинг бэка
issues: [backend#12, TP-Prepare/infra#7] # задачи доски
related: # необязательно: связь с треком этого модуля
- track: ai-review
why: Агентам Stagehand нужен стенд ветки
---
## Цель
…Номер задачи в issues — репо#N или владелец/репо#N; для репозиториев board.owner пишите репо#N
(префикс с владельцем доски тоже работает), чужой репозиторий — владелец/репо#N. Регистр не важен. Карточка
подзадачи на графе показывает «Задачи · N из M готово» и сами задачи по статусам; задача, которой нет в снимке
доски, выводится строкой «— нет на доске» со ссылкой на issue и сборку не роняет. Одна задача может стоять у
нескольких подзадач.
Заголовок, исполнителей, подзадачи и связи страница трека показывает сама — в тексте # Заголовок не нужен.
Пока текста нет, на странице плашка «Описание ещё не написано». У направления с needs (по умолчанию —
fullstack) нужны исполнители со всех перечисленных сторон.
Подтрек — трек с part_of: <id родителя>: он висит под родителем в меню и на графе, у родителя без do
исполнители берутся из подтреков. Вложенность — один уровень.
Подстраницы трека — когда одной страницы мало: файлы tracks/<id>/<page>.md с title во frontmatter и
список во frontmatter трека, он же задаёт порядок:
pages: [contract, auth]Подстраницы появляются в меню под треком и строкой «Документы» в шапке трека. Файл без записи в pages или
запись без файла роняют сборку.
В vitepress dev новый трек появится на графе сразу, а в меню — после перезапуска dev-сервера.
board.json
Снимок доски GitHub Projects (module-graph board snapshot). С ним граф показывает прогресс треков, а карточки и
страницы треков — задачи. Сломанный снимок сборку не роняет: предупреждение в консоли, задачи не показаны.
Ссылки на задачи из репозиториев board.owner выглядят как репо#N, из остальных — владелец/репо#N.
CLI module-graph
Папка модулей — site/modules от текущего каталога или --dir <путь>.
| Команда | Что делает | Вывод и код |
|---|---|---|
| module-graph check | читает и проверяет папку модулей | modules ok: <N> модул…, <M> трек…, 0; ошибка — одна строка в stderr, 1 |
| module-graph check --hook | хук PostToolUse Claude Code: из stdin tool_input.file_path; файл внутри папки модулей — проверка этой папки | молча 0; ошибка — stderr, 2 |
| module-graph board sync | пополняет поле board.field значениями id треков, описание — title из самого нового модуля | sync: добавлено N значений «<field>» |
| module-graph board snapshot <файл> | снимок доски в JSON | snapshot: N задач |
--hook: папка модулей — ближайшая папка-предок файла, в которой естьpeople.yaml. Не JSON, нетfile_path, нет такой папки — 0 молча.board …нужен разделboardвmodule-graph.yamlи токен вGH_TOKEN(другие переменные не читаются). Токен в тексте ошибки заменяется на***. Строка итога и ошибки дописываются вGITHUB_STEP_SUMMARY, если он задан.syncзаменяет список значений поля целиком: значение, добавленное руками в интерфейсе доски между чтением и записью, пропадёт — новые треки добавляйте файлами.- Неизвестная команда — использование в stderr, код 1.
Локально снимок доски:
GH_TOKEN="$(gh auth token)" npx module-graph board snapshot site/modules/board.jsonРазработка
Из корня frontend-packages:
bun install
bun run build && bun run typecheck && bun run test && bun run --filter '*' test:sitebuild—tsdown:src/**/*.ts→dist/*.mjsи.d.mts;.vueкопируются вdist/theme/без изменений,dist/theme/style.cssпишется изareaCss(DEFAULT_CONFIG).typecheck—tsc(TypeScript 7) иvue-tscдля.vue(на TypeScript 6 из@typescript/typescript6: у TypeScript 7 нет JS API, на котором работаетvue-tsc).test:site— тестовый сайтtest/siteна копии фикстуры: пакет копируется вtest/site/node_modules, как послеnpm install, затемtsc,vitepress buildи проверка страниц, затем дымовая проверкаvitepress dev.
Первая публикация
Дальше версии выходят через release-please (release.yml, публикация с OIDC). Первый раз — руками:
- Организация
tp-prepareна npmjs.com. - Публикация
0.1.0:bun run build, затемnpm publishизpackages/vitepress-module-graph. - Trusted publisher пакета на npmjs.com: репозиторий
TP-Prepare/frontend-packages, workflowrelease.yml.
