vitepress-plugin-single-page
Build-time Vite-плагин: для каждой версии документации генерирует single.md — все главы версии, склеенные в одну предрендеренную страницу. Зачем:
- Ctrl+F по всему документу — мгновенно, без N клиентских запросов.
- Pagefind (или другой статический поиск) индексирует версию как единый документ.
- Открытие — обычная статическая HTML-страница: ни iframe, ни JS-водопада.
Установка
bash
npm install -D @ampernic/vitepress-plugin-single-pageИспользование
ts
// .vitepress/config.ts
import { defineConfig } from 'vitepress'
import { SinglePagePlugin } from '@ampernic/vitepress-plugin-single-page'
export default defineConfig({
vite: {
plugins: [
SinglePagePlugin({ distroName: 'alt-server' }),
],
},
})Каждая директория версии под docs/<locale>/ получает single.md, который VitePress собирает в маршрут /<version>/single.
Опции
| Опция | Тип | По умолчанию | Описание |
|---|---|---|---|
srcDir | string | 'docs' | Исходная директория VitePress |
locale | string | 'ru' | Папка локали внутри srcDir |
distroName | string | — | Slug; нужен для поиска .vitepress/sidebars/<distro>/<v>.ts |
versionPattern | RegExp | /^(\d+\.\d+(\.\d+)*|p\d+)$/ | Какие директории считать версиями |
pageName | string | 'single' | Имя генерируемого файла |
titleTemplate | string | '{distro} {version} — на одной странице' | Шаблон заголовка |
frontmatter | object | — | Frontmatter, добавляемый к каждой странице |
sidebarOrder | (srcDir, version, options) => string[] | встроенный | Своя функция порядка глав |
Как работает
- На
configResolved(до того как VitePress сканирует дерево) плагин обходит директории версий. - Для каждой версии читает порядок глав из
.vitepress/sidebars/.../<v>.ts(или изsidebarOrder). - Склеивает
index.mdверсии и всех глав, переписывая относительные пути ассетов так, чтобы они резолвились отsingle.md(Vite дедуплицирует ассеты по контент-хэшу). - Пишет
single.mdв дерево до сканера VitePress — страница появляется как обычный маршрут.
Каждой главе присваивается стабильный якорь sp-<slug> (см. singleAnchorId), на который ссылается клиентский ребайнд сайдбара в теме.
Известные ограничения / edge cases
- Юникод в путях: слаги глав нормализуются через
[^\p{L}\p{N}_-]+(не через\w, который в JS охватывает только латиницу). Без этого кириллический путьinstall-packages-advanced/введение/схлопнулся бы в тот же префикс, что и родительская страницаinstall-packages-advanced/, и якоря{#part-id}дублировались бы между страницами. - Дедупликация анкоров: явные
{#id}и внутристраничные ссылки](#id)префиксуются slug'ом главы, чтобы VitePress не падал на «duplicate user-defined id». dropInitialTOC: срезает висячий## Содержание(заголовок и всё, что до конца документа), если книга-рут уже содержит текстовый TOC. Опция независима от injectTOC, который вставляет<ADBookTOC>в начало склейки.