alt-docs-registry
Единый источник правды для реестра продуктов, разделов и версий документации ALT. Одна YAML-схема products.yaml, Vite-плагин с виртуальным модулем virtual:alt-docs-registry, рантайм-composable useRegistry() и CLI alt-docs.
Пакет заменяет прежние хардкоды PRODUCT_NAMES, ALIASES, ALL_DISTROS, разбросанные по теме и 22 веткам конфига дистрибутивов. Один и тот же реестр читают билд-тайм тема, конвертер publican-docbook-to-vitepress-markdown и рантайм-компоненты навигации.
Установка
pnpm add @ampernic/alt-docs-registryДля скоупа @ampernic из Forgejo прописывается .npmrc в корне проекта:
@ampernic:registry=https://altlinux.space/api/packages/ampernic/npm/CLI alt-docs устанавливается через bin пакета -- запускать pnpm dlx alt-docs ... или локально pnpm exec alt-docs ....
Источник -- products.yaml
Формат описан в schema.ts. Минимальный пример:
schema: 1
locales: [ru, en]
site:
hostname: https://docs.altlinux.space
organization:
name: Базальт СПО
url: https://www.basealt.ru
sections:
- id: server
name: { ru: "Серверные", en: "Server" }
products: [alt-server, alt-domain]
- id: workstation
name: { ru: "Рабочие станции", en: "Workstation" }
products: [alt-workstation, alt-kworkstation]
products:
alt-workstation:
name: { ru: "Альт Рабочая станция" }
tagline: { ru: "Универсальная система для офиса" }
product_link: https://www.basealt.ru/alt-workstation
versions: ["11.2", "11.1", "11.0", "10.4"]
branding:
logo:
col: branding/alt-workstation/logo-col.svg
dark: branding/alt-workstation/logo-dark.svg
accent: "#fa814c"
meta:
isPublic: trueГолова versions считается актуальной. Поле family объединяет legacy-строку (alt-domain-p10) с основной под одной карточкой. site.hostname пробрасывается в ResolvedRegistry.hostname и далее в vitepress-plugin-meta для канонических URL, а site.organization -- в узел schema.org Organization на лендинге.
Использование в конфиге VitePress
// .vitepress/config.mts
import { defineConfig } from 'vitepress'
import { AltDocsRegistryPlugin, createRegistry } from '@ampernic/alt-docs-registry'
import { createSharedConfig } from '@ampernic/vitepress-theme-alt-docs/config'
const { plugin: registryPlugin, resolved } = await createRegistry({
source: 'products.yaml',
fallback: 'https://raw.altlinux.space/alt-docs/docs-vitepress/index/products.yaml',
distro: 'alt-workstation',
locale: 'ru',
emitProductsJson: true,
emitSprite: true,
})
const shared = createSharedConfig({
distroName: 'alt-workstation',
allDistros: resolved.allDistros,
sections: resolved.sections,
productNames: resolved.productNames,
productLinks: resolved.productLinks,
})
export default defineConfig({
...shared,
vite: {
plugins: [registryPlugin, ...(shared.vite?.plugins ?? [])],
},
})createRegistry прогревает snapshot один раз и возвращает и плагин (для vite.plugins), и уже резолвнутый объект ResolvedRegistry. AltDocsRegistryPlugin можно использовать самостоятельно, если snapshot нужен только рантайму.
Использование в компонентах
import { useRegistry } from '@ampernic/alt-docs-registry/composables'
const { registry, merged, refresh } = useRegistry()
// registry.value: билд-тайм snapshot из virtual:alt-docs-registry
// merged.value: runtime cache | build; runtime побеждает
// refresh(): подтягивает свежий /products.json из корня сайтаComposable возвращает shallow-refs, чтобы обновление реестра не рендерило пол-темы. Один модульный кэш на страницу: разные компоненты, зовущие useRegistry(), видят один и тот же fetched snapshot.
CLI alt-docs
Файловые операции, без auto-commit -- git обёртка остаётся за gear-* или CI:
alt-docs product add alt-orchestra \
--section orchestra \
--logoCol ./logo.svg \
--logoDark ./logo-mono.svg
alt-docs version add alt-workstation 11.3 --from 11.2
alt-docs product publish --repo alt-docs/docs-vitepress --token "$ALT_DOCS_TOKEN"
alt-docs check --strictproduct add-- добавляет запись вproducts.yaml, копирует логотипы вdocs/public/branding/<slug>/, привязывает к секции.product remove-- убирает из реестра (ветку не трогает).product publish-- дёргает workflowfull-rebuild.ymlчерез Forgejo API. Требует--tokenилиALT_DOCS_TOKEN.version add-- прописывает новую версию вproducts.yaml(первой в списке = актуальной) и разворачиваетdocs/ru/<X.Y>/из шаблона или предыдущей версии.check-- валидирует schema + факт существования файлов брендинга на диске.--strict= warnings уходят в exit-code 1.
Опции плагина
| Опция | Тип | По умолчанию | Описание |
|---|---|---|---|
source | string | -- | Обязательный. Путь к products.yaml или URL https://... |
fallback | string | -- | Резервный источник -- пробуется, если source не читается |
distro | string | null | null | Слаг текущего дистрибутива. null = index-сборка, показывающая все |
locale | Locale | 'ru' | Локаль, в которую резолвятся LocalizedString-поля |
emitProductsJson | boolean | true | Писать <outDir>/products.json -- ест useRegistry().refresh() в рантайме |
productsJsonName | string | 'products.json' | Имя выходного JSON |
brandingRoots | string[] | ['docs/public', 'public'] | Корни, где искать branding.logo.col/dark. Порядок = приоритет |
emitSprite | boolean | false | Собирать SVG-спрайт всех логотипов как <outDir>/products-sprite.svg |
spriteFileName | string | 'products-sprite.svg' | Имя выходного спрайта |
Что кладётся в ResolvedRegistry
Виртуальный модуль virtual:alt-docs-registry и products.json содержат locale-резолвнутый снимок:
| Поле | Описание |
|---|---|
hostname | Копия site.hostname из yaml |
organization | Копия site.organization: издатель, которого vitepress-plugin-meta печатает как узел schema.org Organization на лендинге |
allDistros | Отсортированный список слагов всех продуктов |
sections | { id, name, products } -- имена уже резолвнуты в текущую локаль |
productNames | slug -> localized name |
productBrandingKeys | slug -> ключ спрайта (учтён branding.sharedWith) |
productTaglines | slug -> localized tagline |
productLinks | slug -> product_link (внешняя страница продукта) |
productFamilyPrimary | slug -> primary slug семьи (self, если не в семье) |
productFamilyMembers | primary slug -> [primary, ...secondaries] |
productVersions | slug -> versions[] (позволяет primary landing показать все ветки без cross-site fetch) |
currentDistro | Копия опции distro |
locale | Копия опции locale |
Нюансы
- Парсер требует наличия
schema: 1в yaml. Дополнительные поля не ломают -- ломает только несовпадение мажорной версии. parseRegistryможет вернутьissues[]сseverity: 'error'-- плагин в этом случае падает приconfigResolved, а не молча собирает битый snapshot.- Дистрибутив, у которого пусто
versions[], не считается ошибкой -- в переключателе отображается заглушкой без версий (нужно для распорок под будущие продукты). - Флаг
emitSpriteвключайте только когда тема реально пользуется путёмproducts-sprite.svg-- иначе платите килобайтами в бандле впустую. parseRegistryумеет обрабатывать неизвестные поля мягко: пишет warning, но валидирует остальное.field: siteпри merge из YAML восстанавливается вручную -- в старых версиях парсера теряется. Сейчас чинится наверху; смотритеtest/site-field.test.tsперед патчами loader'а.