From 07542330b5062b1111fc7f30cf56d6fc2631415d Mon Sep 17 00:00:00 2001 From: "S.Gromov" Date: Sat, 2 May 2026 06:53:35 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B8=20llm?= =?UTF-8?q?s=20=D0=BD=D0=B0=20markdown-=D1=84=D0=B0=D0=B9=D0=BB=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - обновлены ссылки llms.txt на доступные .md-файлы - добавлено копирование markdown-файлов в публичную статику - исключена docs/public из сканирования VitePress и индекса Git - добавлена пометка для локальной копии ARCHITECTURE.md --- .gitignore | 2 +- .vitepress/config.ts | 1 + generate.ts | 60 ++++++++++++++++++++++++++++++++---------- public/ARCHITECTURE.md | 6 ++++- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 3575c3d..fab8adf 100644 --- a/.gitignore +++ b/.gitignore @@ -135,6 +135,7 @@ dist .vitepress/cache .vitepress/dist docs/.vitepress +docs/public/ # Generated artifacts public/docs/ @@ -149,4 +150,3 @@ dist # Рабочие заметки notes - diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 2e51215..8cbf698 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -14,6 +14,7 @@ const sidebar = [ export default defineConfig({ srcDir: 'docs', + srcExclude: ['public/**'], outDir: 'public/docs', title: 'SLM Design', description: 'Правила и стандарты архитектуры проекта', diff --git a/generate.ts b/generate.ts index 2a12ec3..75b7811 100644 --- a/generate.ts +++ b/generate.ts @@ -5,7 +5,12 @@ import { execFileSync } from "child_process"; const SRC_DIR = "./docs"; const PUBLIC_DIR = "./public"; +const DOCS_PUBLIC_DIR = path.join(SRC_DIR, "public"); +const DOC_ROUTE_PREFIX = "/docs"; const PUBLIC_ARCHITECTURE_FILE = "ARCHITECTURE.md"; +const PUBLIC_ARCHITECTURE_NOTICE = `> Локальная копия канонической спецификации SLM Design. +> Источник: https://slm-design.gromlab.ru/ARCHITECTURE.md +> Не редактировать вручную в этом проекте.`; interface SidebarItem { text: string; @@ -43,15 +48,25 @@ function parseSidebar(): SidebarGroup[] { const SIDEBAR = parseSidebar(); +function linkToFileRel(link: string): string { + const rel = link.replace(/^\//, ""); + if (rel === "" || rel.endsWith("/")) return `${rel}index.md`; + return `${rel}.md`; +} + +function fileRelToRoute(file: string): string { + const route = file.endsWith("/index.md") + ? file.replace(/index\.md$/, "") + : file.replace(/\.md$/, ""); + return `${DOC_ROUTE_PREFIX}/${route}`; +} + +function fileRelToMdUrl(file: string): string { + return `${DOC_ROUTE_PREFIX}/${file}`; +} + function getAllFiles(): string[] { - return SIDEBAR.flatMap((g) => - g.items.map((item) => { - const rel = item.link.replace(/^\//, "") + ".md"; - const indexPath = rel.replace(/\.md$/, "/index.md"); - const filePath = path.join(SRC_DIR, indexPath); - return fs.existsSync(filePath) ? indexPath : rel; - }) - ); + return SIDEBAR.flatMap((g) => g.items.map((item) => linkToFileRel(item.link))); } const stripFrontmatter = (content: string) => @@ -84,7 +99,7 @@ const buildArchitectureMarkdown = (routePrefix: string) => { const content = stripRulesLink(stripFrontmatter(raw)).trim(); if (!content) continue; - const route = routePrefix + "/" + file.replace(/\.md$/, ""); + const route = routePrefix + fileRelToRoute(file).replace(DOC_ROUTE_PREFIX, ""); const processed = file.endsWith("index.md") ? content : shiftHeadings(content); parts.push(`\n${processed}`); } @@ -99,9 +114,7 @@ function buildLlms() { for (const group of SIDEBAR) { parts.push(`## ${group.text}`); for (const item of group.items) { - const rel = item.link.replace(/^\//, "") + ".md"; - const indexPath = rel.replace(/\.md$/, "/index.md"); - const fileRel = fs.existsSync(path.join(SRC_DIR, indexPath)) ? indexPath : rel; + const fileRel = linkToFileRel(item.link); const filePath = path.join(SRC_DIR, fileRel); let desc = ""; if (fs.existsSync(filePath)) { @@ -109,7 +122,7 @@ function buildLlms() { const fm = raw.match(/^---[\s\S]*?---\n*/m); desc = fm ? fm[0].match(/description:\s*(.+)/)?.[1] || "" : ""; } - const route = "/docs" + item.link; + const route = fileRelToMdUrl(fileRel); const line = desc ? `- [${item.text}](${route}): ${desc}` : `- [${item.text}](${route})`; @@ -130,10 +143,28 @@ function buildLlmsFull() { console.log(`llms-full.txt создан: ${outPath}`); } +function copyMarkdownFiles() { + fs.rmSync(DOCS_PUBLIC_DIR, { recursive: true, force: true }); + + let copied = 0; + for (const file of getAllFiles()) { + const src = path.join(SRC_DIR, file); + if (!fs.existsSync(src)) continue; + + const dest = path.join(DOCS_PUBLIC_DIR, file); + fs.mkdirSync(path.dirname(dest), { recursive: true }); + fs.copyFileSync(src, dest); + copied++; + } + + console.log(`скопировано ${copied} .md-файлов в ${DOCS_PUBLIC_DIR}`); +} + function buildPublicArchitecture() { const outPath = path.join(PUBLIC_DIR, PUBLIC_ARCHITECTURE_FILE); + const content = `${PUBLIC_ARCHITECTURE_NOTICE}\n\n${buildArchitectureMarkdown("/docs")}`; fs.mkdirSync(PUBLIC_DIR, { recursive: true }); - fs.writeFileSync(outPath, buildArchitectureMarkdown("/docs"), "utf8"); + fs.writeFileSync(outPath, content, "utf8"); console.log(`${PUBLIC_ARCHITECTURE_FILE} создан: ${outPath}`); } @@ -180,6 +211,7 @@ function buildReadme() { buildLlms(); buildLlmsFull(); +copyMarkdownFiles(); buildPublicArchitecture(); buildZip(); buildReadme(); diff --git a/public/ARCHITECTURE.md b/public/ARCHITECTURE.md index 2cfc281..d43a194 100644 --- a/public/ARCHITECTURE.md +++ b/public/ARCHITECTURE.md @@ -1,4 +1,8 @@ - +> Локальная копия канонической спецификации SLM Design. +> Источник: https://slm-design.gromlab.ru/ARCHITECTURE.md +> Не редактировать вручную в этом проекте. + + # SLM Design Scoped Layered Module Design — модульная архитектура фронтенд-приложений. Код организован по слоям ответственности, а модуль содержит всё, что ему нужно: компоненты, хуки, сторы, типы, стили.