Files
nextjs-style-guide/generate-llms.ts

572 lines
18 KiB
TypeScript
Raw Normal View History

feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
import path from 'node:path';
import fs from 'node:fs';
import os from 'node:os';
import { execFileSync } from 'node:child_process';
import config from './.vitepress/config';
/** Версия сборки. Передаётся CI через ENV; локально — `dev`. */
const VERSION = process.env.BUILD_VERSION || 'dev';
const BUILD_DATE = new Date().toISOString();
/** Корневая папка для генерируемой статики (попадает в build dist). */
const PUBLIC_DIR = 'docs/public';
/** Префикс URL документации. Соответствует структуре `docs/docs/...`. */
const DOC_PREFIX = '/docs/';
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
/** Канонический хост сайта (для sitemap/robots). Можно переопределить через ENV. */
const SITE_URL = (process.env.SITE_URL || 'https://nextjs-style-guide.gromlab.ru').replace(/\/$/, '');
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
interface SidebarItem {
text: string;
link?: string;
items?: SidebarItem[];
collapsed?: boolean;
}
interface Entry {
/** Название группы верхнего уровня (sidebar[].text) */
section: string;
/** Префикс из вложенной группы (например "Архитектура") */
prefix: string | null;
/** Текст пункта в sidebar */
text: string;
/** Ссылка из sidebar */
link: string;
}
/** Разобрать YAML frontmatter (плоский, без вложенностей) */
const parseFrontmatter = (
content: string,
): { data: Record<string, string>; body: string } => {
const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
if (!match) return { data: {}, body: content };
const data: Record<string, string> = {};
for (const line of match[1].split('\n')) {
const lineMatch = line.match(/^([^:]+):\s*(.*)$/);
if (!lineMatch) continue;
let value = lineMatch[2].trim();
if (
(value.startsWith('"') && value.endsWith('"')) ||
(value.startsWith("'") && value.endsWith("'"))
) {
value = value.slice(1, -1);
}
data[lineMatch[1].trim()] = value;
}
return { data, body: match[2] };
};
/** Первый абзац после h1 — однострочное описание для llms.txt */
const firstParagraphAfterH1 = (body: string): string | null => {
const lines = body.split('\n');
const h1Idx = lines.findIndex((l) => /^#\s/.test(l));
if (h1Idx === -1) return null;
let i = h1Idx + 1;
while (i < lines.length && lines[i].trim() === '') i++;
const para: string[] = [];
while (
i < lines.length &&
lines[i].trim() !== '' &&
!lines[i].startsWith('#')
) {
para.push(lines[i].trim());
i++;
}
return para.join(' ').trim() || null;
};
/**
* Преобразовать sidebar `link` (например `/docs/foo`) в относительный
* путь файла внутри `docs/docs/`. Префикс `/docs/` отрезается.
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
*/
const linkToRel = (link: string): string => {
let rel = link.startsWith(DOC_PREFIX)
? link.slice(DOC_PREFIX.length)
: link.replace(/^\//, '');
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
if (rel === '' || rel.endsWith('/')) {
rel += 'index.md';
} else {
rel += '.md';
}
return rel;
};
const linkToFilePath = (link: string): string =>
path.join('docs/docs', linkToRel(link));
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
/** Абсолютный URL `.md`-копии страницы на сайте. */
const linkToSiteUrl = (link: string): string =>
`${DOC_PREFIX}${linkToRel(link)}`;
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
/**
* Развернуть sidebar в плоский список с сохранением группы и
* накопленного префикса вложенных групп. Поддерживает произвольную
* глубину вложенности префиксы подгрупп склеиваются через `: `.
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
*/
const flattenSidebar = (sidebar: SidebarItem[]): Entry[] => {
const entries: Entry[] = [];
const walk = (
items: SidebarItem[],
section: string,
prefix: string | null,
): void => {
for (const item of items) {
const hasChildren = !!item.items && item.items.length > 0;
if (item.link) {
entries.push({ section, prefix, text: item.text, link: item.link });
}
if (hasChildren) {
const nextPrefix = prefix ? `${prefix}: ${item.text}` : item.text;
walk(item.items!, section, nextPrefix);
}
}
};
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
for (const top of sidebar) {
const hasChildren = !!top.items && top.items.length > 0;
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
if (top.link && !hasChildren) {
entries.push({ section: top.text, prefix: null, text: top.text, link: top.link });
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
continue;
}
if (hasChildren) {
walk(top.items!, top.text, null);
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
}
}
return entries;
};
const groupBySection = (entries: Entry[]): Map<string, Entry[]> => {
const map = new Map<string, Entry[]>();
for (const entry of entries) {
const list = map.get(entry.section);
if (list) list.push(entry);
else map.set(entry.section, [entry]);
}
return map;
};
interface SiteConfig {
title: string;
description: string;
themeConfig: { sidebar: SidebarItem[] };
llmsBlockquote?: string;
llmsContext?: string;
}
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
const cfg = config as unknown as SiteConfig;
const buildLlms = (): void => {
const sidebar = cfg.themeConfig.sidebar;
const blockquote = cfg.llmsBlockquote ?? cfg.description;
const context = cfg.llmsContext;
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
const entries = flattenSidebar(sidebar);
const grouped = groupBySection(entries);
const lines: string[] = [];
lines.push(`# ${cfg.title}`);
lines.push('');
lines.push(`> ${blockquote}`);
lines.push('');
if (context) {
lines.push(context);
lines.push('');
}
for (const [section, items] of grouped) {
lines.push(`## ${section}`);
lines.push('');
for (const entry of items) {
const filePath = linkToFilePath(entry.link);
const url = linkToSiteUrl(entry.link);
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
let description: string | null = null;
if (fs.existsSync(filePath)) {
const raw = fs.readFileSync(filePath, 'utf8');
const { data, body } = parseFrontmatter(raw);
description = data.description || firstParagraphAfterH1(body);
} else {
console.warn(`файл не найден: ${filePath}`);
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
}
const display = entry.prefix
? `${entry.prefix}: ${entry.text}`
: entry.text;
const descPart = description ? `: ${description}` : '';
lines.push(`- [${display}](${url})${descPart}`);
}
lines.push('');
}
fs.mkdirSync(PUBLIC_DIR, { recursive: true });
const outFile = path.join(PUBLIC_DIR, 'llms.txt');
fs.writeFileSync(outFile, lines.join('\n'), 'utf8');
console.log(`${outFile} создан`);
};
/** Рекурсивно скопировать дерево, фильтруя по предикату. */
const copyDirSync = (
src: string,
dest: string,
filter: (name: string) => boolean = () => true,
): number => {
let count = 0;
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
fs.mkdirSync(destPath, { recursive: true });
count += copyDirSync(srcPath, destPath, filter);
} else if (entry.isFile() && filter(entry.name)) {
fs.mkdirSync(dest, { recursive: true });
fs.copyFileSync(srcPath, destPath);
count++;
}
}
return count;
};
/**
* Скопировать все `.md`-файлы документации в `docs/public/docs/`,
* чтобы они попали в build `dist/` и были доступны по URL `/docs/path.md`.
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
*/
const copyMdFiles = (): void => {
const srcDir = 'docs/docs';
const destDir = path.join(PUBLIC_DIR, 'docs');
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
if (!fs.existsSync(srcDir)) return;
const copied = copyDirSync(srcDir, destDir, (name) => name.endsWith('.md'));
console.log(`скопировано ${copied} .md-файлов в ${destDir}`);
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
};
/**
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
* Преобразовать sidebar `link` в относительный путь файла внутри архива
* (от корня папки `nextjs-style-guide/`).
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
*/
const linkToArchiveRel = (link: string): string => {
let rel = link.startsWith(DOC_PREFIX)
? link.slice(DOC_PREFIX.length)
: link.replace(/^\//, '');
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
if (rel === '' || rel.endsWith('/')) {
rel += 'index.md';
} else {
rel += '.md';
}
return rel;
};
/**
* Заменить во всех `.md` архива ссылки `[text](/docs/foo)` на относительные
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
* пути от расположения файла. Без этого внутренние ссылки в распакованной
* папке не работают.
*/
const transformLinksInDir = (rootDir: string): void => {
const linkRe = /\]\(\/docs\/([^)\s#]*)(#[^)]*)?\)/g;
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
const walk = (dir: string): void => {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
walk(full);
continue;
}
if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
const content = fs.readFileSync(full, 'utf8');
const fileDir = path.dirname(full);
const updated = content.replace(linkRe, (_match, route, hash = '') => {
const targetRel = linkToArchiveRel(`${DOC_PREFIX}${route}`);
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
const targetAbs = path.join(rootDir, targetRel);
let rel = path.relative(fileDir, targetAbs);
if (!rel.startsWith('.')) rel = './' + rel;
return `](${rel}${hash})`;
});
if (updated !== content) {
fs.writeFileSync(full, updated, 'utf8');
}
}
};
walk(rootDir);
};
/**
* Сгенерировать `README.md` точка входа архива. Карта документации
* с относительными ссылками, описаниями из frontmatter/первого абзаца
* и метаинфо сборки.
*/
const buildArchiveReadme = (rootDir: string): void => {
const sidebar = cfg.themeConfig.sidebar;
const blockquote = cfg.llmsBlockquote ?? cfg.description ?? '';
const context = cfg.llmsContext;
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
const entries = flattenSidebar(sidebar).filter(
// «Главная» из sidebar — это страница раздела для веба, в архиве не нужна.
(e) => e.section !== 'Главная',
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
);
const grouped = groupBySection(entries);
const lines: string[] = [];
lines.push(`# ${cfg.title}`);
lines.push('');
if (blockquote) {
lines.push(`> ${blockquote}`);
lines.push('');
}
if (context) {
lines.push(context);
lines.push('');
}
lines.push('## Содержание');
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
lines.push('');
for (const [section, items] of grouped) {
lines.push(`### ${section}`);
lines.push('');
for (const entry of items) {
const targetRel = './' + linkToArchiveRel(entry.link);
const filePath = path.join(rootDir, linkToArchiveRel(entry.link));
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
let description: string | null = null;
if (fs.existsSync(filePath)) {
const raw = fs.readFileSync(filePath, 'utf8');
const { data, body } = parseFrontmatter(raw);
description = data.description || firstParagraphAfterH1(body);
}
const display = entry.prefix
? `${entry.prefix}: ${entry.text}`
: entry.text;
const descPart = description ? `${description}` : '';
lines.push(`- [${display}](${targetRel})${descPart}`);
}
lines.push('');
}
lines.push('---');
lines.push('');
lines.push(`Версия: ${VERSION} · Сборка: ${BUILD_DATE}`);
lines.push('');
fs.writeFileSync(path.join(rootDir, 'README.md'), lines.join('\n'), 'utf8');
};
/**
* Собрать `nextjs-style-guide.zip`. Внутри папка `nextjs-style-guide/`
* с `.md`-файлами, README, `llms-full.txt` и `VERSION`. Внутренние ссылки
* преобразуются в относительные.
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
*/
const buildZip = (): void => {
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'nsg-'));
const stage = path.join(tmpRoot, 'nextjs-style-guide');
fs.mkdirSync(stage, { recursive: true });
// 1. Копируем все .md в staging.
copyDirSync('docs/docs', stage, (name) => name.endsWith('.md'));
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
// 2. Удаляем веб-index.md — в архиве его роль выполняет README.md.
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
const indexPath = path.join(stage, 'index.md');
if (fs.existsSync(indexPath)) fs.unlinkSync(indexPath);
// 3. Преобразуем абсолютные ссылки `/docs/...` в относительные.
transformLinksInDir(stage);
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
// 4. Генерируем точку входа README.md.
buildArchiveReadme(stage);
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
// 5. Кладём llms-full.txt — удобно для одноразового чтения LLM.
const llmsFullSrc = path.join(PUBLIC_DIR, 'llms-full.txt');
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
if (fs.existsSync(llmsFullSrc)) {
fs.copyFileSync(llmsFullSrc, path.join(stage, 'llms-full.txt'));
}
// 6. Метаинформация сборки.
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
fs.writeFileSync(
path.join(stage, 'VERSION'),
`${VERSION}\n${BUILD_DATE}\n`,
);
const outFile = path.resolve(PUBLIC_DIR, 'nextjs-style-guide.zip');
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
fs.rmSync(outFile, { force: true });
execFileSync('zip', ['-rq', outFile, 'nextjs-style-guide'], {
cwd: tmpRoot,
});
fs.rmSync(tmpRoot, { recursive: true, force: true });
console.log(`${outFile} создан (${VERSION})`);
};
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
/** Удалить YAML frontmatter из исходника `.md`. */
const stripFrontmatter = (content: string): string =>
content.replace(/^---\n[\s\S]*?\n---\n*/, '');
/**
* Сдвинуть уровень заголовков на 1 вниз (h1h2, h2h3, ...).
* Игнорирует строки внутри блоков кода.
*/
const shiftHeadings = (content: string): string => {
const lines = content.split('\n');
let inCodeBlock = false;
return lines
.map((line) => {
if (line.startsWith('```')) inCodeBlock = !inCodeBlock;
if (inCodeBlock) return line;
if (/^#{1,5}\s/.test(line)) return '#' + line;
return line;
})
.join('\n');
};
/**
* Собрать `llms-full.txt` все страницы в одном файле.
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
* Порядок страниц повторяет порядок в sidebar.
*/
const buildLlmsFull = (): void => {
const sidebar = cfg.themeConfig.sidebar;
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
const entries = flattenSidebar(sidebar);
const blockquote = cfg.llmsBlockquote ?? cfg.description ?? '';
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
const parts: string[] = [];
parts.push(`# ${cfg.title}`);
parts.push('');
if (blockquote) parts.push(`> ${blockquote}`);
if (cfg.llmsContext) {
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
parts.push('');
parts.push(cfg.llmsContext);
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
}
parts.push('');
for (const entry of entries) {
const filePath = linkToFilePath(entry.link);
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
if (!fs.existsSync(filePath)) continue;
const raw = fs.readFileSync(filePath, 'utf8');
const content = shiftHeadings(stripFrontmatter(raw)).trim();
if (!content) continue;
// Мета-якорь: путь страницы для ориентации LLM
parts.push(`<!-- ${entry.link} -->`);
parts.push('');
parts.push(content);
parts.push('');
}
fs.mkdirSync(PUBLIC_DIR, { recursive: true });
const outFile = path.join(PUBLIC_DIR, 'llms-full.txt');
feat: llms-full.txt, README архива и доработка лендинга - добавлен генератор llms-full.txt: вся документация локали в одном файле с мета-якорями, порядок повторяет sidebar - архив теперь содержит README.md как точку входа: карта документации с относительными ссылками, описаниями и метаинфо сборки - ссылки /ru/... в .md-файлах архива преобразуются в относительные пути (через path.relative) — внутренняя навигация работает локально - веб-index.md удаляется из архива (его роль выполняет README.md) - llms-full.txt добавлен в архив для одноразового чтения LLM - в sidebar добавлен пункт «Главная» / «Home» со ссылкой на корень локали - карточка «Ассистенту» на лендинге: две кнопки llms.txt и llms-full.txt с открытием в новой вкладке - активирована карточка «Скачать правила» (ru) с ссылкой на zip-архив - удалён устаревший блок «Для ассистентов» из docs/{ru,en}/index.md - обновлены описания на главных локалей и заменён FSD на SLM в EN - в манифесте появилось поле llmsFull рядом с llms
2026-04-25 19:56:44 +03:00
fs.writeFileSync(outFile, parts.join('\n'), 'utf8');
console.log(`${outFile} создан`);
};
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
/** Манифест сборки — для лендинга и внешних потребителей. */
const writeManifest = (): void => {
const manifest = {
version: VERSION,
buildDate: BUILD_DATE,
llms: '/llms.txt',
llmsFull: '/llms-full.txt',
zip: '/nextjs-style-guide.zip',
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
};
fs.mkdirSync(PUBLIC_DIR, { recursive: true });
fs.writeFileSync(
path.join(PUBLIC_DIR, 'manifest.json'),
JSON.stringify(manifest, null, 2),
'utf8',
);
console.log(`${PUBLIC_DIR}/manifest.json создан`);
};
/**
* Сгенерировать `robots.txt` с указанием sitemap и явными ссылками
* на llms.txt/llms-full.txt стандартные файлы, которые читают агенты.
*/
const buildRobots = (): void => {
const lines = [
'User-agent: *',
'Allow: /',
'',
`Sitemap: ${SITE_URL}/sitemap.xml`,
'',
'# Карта документации для AI-агентов:',
`# ${SITE_URL}/llms.txt`,
`# ${SITE_URL}/llms-full.txt`,
'',
];
fs.mkdirSync(PUBLIC_DIR, { recursive: true });
fs.writeFileSync(path.join(PUBLIC_DIR, 'robots.txt'), lines.join('\n'), 'utf8');
console.log(`${PUBLIC_DIR}/robots.txt создан`);
};
/**
* Сгенерировать `sitemap.xml` из sidebar + корневые ресурсы для LLM
* (llms.txt, llms-full.txt) чтобы агенты, читающие sitemap, видели их.
*/
const buildSitemap = (): void => {
const sidebar = cfg.themeConfig.sidebar;
const entries = flattenSidebar(sidebar);
const urls = new Set<string>();
urls.add(`${SITE_URL}/`);
urls.add(`${SITE_URL}/llms.txt`);
urls.add(`${SITE_URL}/llms-full.txt`);
for (const entry of entries) {
const link = entry.link;
// VitePress отдаёт страницы как HTML; для index — каталог со слешем.
const url = link.endsWith('/') ? `${SITE_URL}${link}` : `${SITE_URL}${link}.html`;
urls.add(url);
}
const today = BUILD_DATE.slice(0, 10);
const xml = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
...[...urls].map(
(loc) => ` <url><loc>${loc}</loc><lastmod>${today}</lastmod></url>`,
),
'</urlset>',
'',
].join('\n');
fs.mkdirSync(PUBLIC_DIR, { recursive: true });
fs.writeFileSync(path.join(PUBLIC_DIR, 'sitemap.xml'), xml, 'utf8');
console.log(`${PUBLIC_DIR}/sitemap.xml создан`);
};
/** Скопировать `index.md` документации в корневой README без frontmatter. */
const buildReadme = (): void => {
const indexPath = 'docs/docs/index.md';
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
if (!fs.existsSync(indexPath)) {
console.warn(`Пропуск README.md: ${indexPath} не найден`);
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
return;
}
const raw = fs.readFileSync(indexPath, 'utf8');
const { body } = parseFrontmatter(raw);
fs.writeFileSync('README.md', body.trimStart(), 'utf8');
console.log(`README.md обновлён из ${indexPath}`);
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
};
buildLlms();
buildLlmsFull();
copyMdFiles();
buildZip();
feat: генерация llms.txt, лендинг с выбором языка и ZIP-архивов - удалён concat-md.js: вместо единого RULES.md теперь llms.txt - добавлен generate-llms.ts: собирает llms.txt из sidebar config, копирует .md-файлы для отдачи LLM и упаковывает ZIP-архивы по локалям - добавлен корневой /llms.txt как роутер на /ru/llms.txt и /en/llms.txt - добавлен манифест /manifest.json со ссылками и версией сборки - добавлен лендинг docs/index.md (layout: false) с автоопределением языка, переключателями языка и темы - английская локаль временно заблокирована: карточки как заглушки, ссылка на /en/ в роутере без href - добавлены поля llmsBlockquote и llmsContext в локали для технодокументационного описания в llms.txt - разделены VitePress-локали: root (только лендинг), ru (/ru/), en (/en/) - добавлен srcExclude: ['public/**'] чтобы VitePress не рендерил сгенерированные .md как страницы - добавлен Vite-плагин для отдачи .txt и .md с charset=utf-8 - добавлена секция в Caddyfile для текстовых файлов - BUILD_VERSION пробрасывается из Gitea CI через docker --build-arg и подставляется в лендинг через Vite define - Dockerfile: установка zip, npm run llms перед npm run build - обновлены внутренние ссылки в docs/ru/**/*.md на префикс /ru/ - обновлены AGENTS.md и CONTRIBUTING.md под новый процесс - README/README_RU генерируются из docs/{lang}/index.md, остаются в репо
2026-04-25 18:06:27 +03:00
writeManifest();
buildRobots();
buildSitemap();
buildReadme();