From 1a1de7cad483d99ed1f704812c9b56ac8648d203 Mon Sep 17 00:00:00 2001 From: "S.Gromov" Date: Sat, 2 May 2026 18:51:44 +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=D0=B4=D0=BE=D1=81=D1=82=D1=83=D0=BF=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=B0=D1=80=D1=82=D0=B5=D1=84=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D0=B2=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - добавлены HTML-подсказки для обнаружения llms.txt агентами - обновлена карточка скачивания спецификации и архива - добавлен раздел с порядком чтения спецификации - исправлена генерация ссылок для single-file, Markdown и ZIP - обновлены сгенерированные README.md и ARCHITECTURE.md --- .vitepress/config.ts | 6 ++ README.md | 10 +++ docs/architecture/index.md | 10 +++ generate.ts | 69 ++++++++++++++++++- index.html | 20 +++++- public/ARCHITECTURE.md | 14 +++- src/screens/home/config/home-screen.config.ts | 17 +++-- src/screens/home/home.screen.tsx | 7 +- 8 files changed, 143 insertions(+), 10 deletions(-) diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 8cbf698..f6ad7c1 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -20,6 +20,12 @@ export default defineConfig({ description: 'Правила и стандарты архитектуры проекта', base: '/docs/', cleanUrls: true, + head: [ + ['meta', { name: 'llms', content: '/llms.txt' }], + ['link', { rel: 'alternate llms', type: 'text/plain', href: '/llms.txt', title: 'llms.txt' }], + ['link', { rel: 'alternate', type: 'text/plain', href: '/llms-full.txt', title: 'llms-full.txt' }], + ['link', { rel: 'alternate', type: 'text/markdown', href: '/ARCHITECTURE.md', title: 'ARCHITECTURE.md' }], + ], themeConfig: { sidebar, diff --git a/README.md b/README.md index 4f608f2..271a0d9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,16 @@ # SLM Design Scoped Layered Module Design — модульная архитектура фронтенд-приложений. Код организован по слоям ответственности, а модуль содержит всё, что ему нужно: компоненты, хуки, сторы, типы, стили. +## Разделы спецификации + +Спецификация SLM Design состоит из нескольких связанных разделов. Этот обзор даёт общий контекст, а детальные правила описаны дальше: + +- [Слои](docs/architecture/layers.md) — уровни организации `src/`, направление зависимостей и зона ответственности каждого слоя. +- [Модули](docs/architecture/modules.md) — границы ответственности, публичный API, типы модулей и отличие модуля от компонента. +- [Сегменты](docs/architecture/segments.md) — внутренние папки модуля (`ui/`, `parts/`, `hooks/`, `types/` и другие) и правила размещения файлов. + +Рекомендуемый порядок чтения: обзор → слои → модули → сегменты. + ## Преимущества ### Вертикальная организация домена diff --git a/docs/architecture/index.md b/docs/architecture/index.md index a44600a..544cc22 100644 --- a/docs/architecture/index.md +++ b/docs/architecture/index.md @@ -6,6 +6,16 @@ description: Назначение архитектуры, ключевые пр # SLM Design Scoped Layered Module Design — модульная архитектура фронтенд-приложений. Код организован по слоям ответственности, а модуль содержит всё, что ему нужно: компоненты, хуки, сторы, типы, стили. +## Разделы спецификации + +Спецификация SLM Design состоит из нескольких связанных разделов. Этот обзор даёт общий контекст, а детальные правила описаны дальше: + +- [Слои](/architecture/layers) — уровни организации `src/`, направление зависимостей и зона ответственности каждого слоя. +- [Модули](/architecture/modules) — границы ответственности, публичный API, типы модулей и отличие модуля от компонента. +- [Сегменты](/architecture/segments) — внутренние папки модуля (`ui/`, `parts/`, `hooks/`, `types/` и другие) и правила размещения файлов. + +Рекомендуемый порядок чтения: обзор → слои → модули → сегменты. + ## Преимущества ### Вертикальная организация домена diff --git a/generate.ts b/generate.ts index 75b7811..eb559fb 100644 --- a/generate.ts +++ b/generate.ts @@ -65,6 +65,35 @@ function fileRelToMdUrl(file: string): string { return `${DOC_ROUTE_PREFIX}/${file}`; } +const ARCHITECTURE_LINK_RE = /\]\((\/architecture(?:\/[^)\s#]*)?)(#[^)\s]*)?\)/g; + +function architectureRouteToFileRel(route: string): string { + if (route.replace(/\/$/, "") === "/architecture") return "architecture/index.md"; + return linkToFileRel(route); +} + +function transformArchitectureLinks( + content: string, + toHref: (route: string, hash: string) => string, +): string { + return content.replace(ARCHITECTURE_LINK_RE, (_match, route: string, hash = "") => { + return `](${toHref(route, hash)})`; + }); +} + +function transformArchiveLinks(content: string): string { + return transformArchitectureLinks(content, (route, hash) => { + const fileName = path.basename(architectureRouteToFileRel(route)); + return `./${fileName}${hash}`; + }); +} + +function transformSiteMarkdownLinks(content: string): string { + return transformArchitectureLinks(content, (route, hash) => { + return `${fileRelToMdUrl(architectureRouteToFileRel(route))}${hash}`; + }); +} + function getAllFiles(): string[] { return SIDEBAR.flatMap((g) => g.items.map((item) => linkToFileRel(item.link))); } @@ -75,6 +104,38 @@ const stripFrontmatter = (content: string) => const stripRulesLink = (content: string) => content.replace(/[\s\S]*?\n*/g, ""); +function slugifyHeading(heading: string): string { + return heading + .trim() + .replace(/[`*_~[\]()]/g, "") + .toLowerCase() + .replace(/[^\p{L}\p{N}\s-]/gu, "") + .trim() + .replace(/\s+/g, "-"); +} + +function fileRelToSingleFileAnchor(file: string): string { + const filePath = path.join(SRC_DIR, file); + if (!fs.existsSync(filePath)) return slugifyHeading(path.basename(file, ".md")); + + const raw = stripFrontmatter(fs.readFileSync(filePath, "utf8")); + const title = raw.match(/^#\s+(.+)$/m)?.[1]; + return slugifyHeading(title ?? path.basename(file, ".md")); +} + +function transformSingleFileLinks(content: string): string { + return transformArchitectureLinks(content, (route, hash) => { + if (hash) return hash; + return `#${fileRelToSingleFileAnchor(architectureRouteToFileRel(route))}`; + }); +} + +function transformReadmeLinks(content: string): string { + return transformArchitectureLinks(content, (route, hash) => { + return `docs/${architectureRouteToFileRel(route)}${hash}`; + }); +} + const shiftHeadings = (content: string) => { const lines = content.split("\n"); let inCodeBlock = false; @@ -100,7 +161,8 @@ const buildArchitectureMarkdown = (routePrefix: string) => { if (!content) continue; const route = routePrefix + fileRelToRoute(file).replace(DOC_ROUTE_PREFIX, ""); - const processed = file.endsWith("index.md") ? content : shiftHeadings(content); + const shifted = file.endsWith("index.md") ? content : shiftHeadings(content); + const processed = transformSingleFileLinks(shifted); parts.push(`\n${processed}`); } @@ -151,9 +213,10 @@ function copyMarkdownFiles() { const src = path.join(SRC_DIR, file); if (!fs.existsSync(src)) continue; + const content = transformSiteMarkdownLinks(fs.readFileSync(src, "utf8")); const dest = path.join(DOCS_PUBLIC_DIR, file); fs.mkdirSync(path.dirname(dest), { recursive: true }); - fs.copyFileSync(src, dest); + fs.writeFileSync(dest, content, "utf8"); copied++; } @@ -179,6 +242,7 @@ function buildZip() { if (!fs.existsSync(src)) continue; let content = fs.readFileSync(src, "utf8"); content = stripRulesLink(stripFrontmatter(content)).trim(); + content = transformArchiveLinks(content); const destName = path.basename(file); fs.writeFileSync(path.join(tmpDir, destName), content, "utf8"); } @@ -205,6 +269,7 @@ function buildReadme() { let content = stripFrontmatter(fs.readFileSync(indexPath, "utf8")); content = content.replace(/[\s\S]*?\n*/g, ""); + content = transformReadmeLinks(content); fs.writeFileSync("./README.md", content, "utf8"); console.log("README.md создан"); } diff --git a/index.html b/index.html index 25945e0..7324688 100644 --- a/index.html +++ b/index.html @@ -5,10 +5,28 @@ SLM Design + + + + -
+
+
+

SLM Design

+

Scoped Layered Module Design — модульная архитектура фронтенд-приложений.

+ +
+
diff --git a/public/ARCHITECTURE.md b/public/ARCHITECTURE.md index d43a194..78829e1 100644 --- a/public/ARCHITECTURE.md +++ b/public/ARCHITECTURE.md @@ -6,6 +6,16 @@ # SLM Design Scoped Layered Module Design — модульная архитектура фронтенд-приложений. Код организован по слоям ответственности, а модуль содержит всё, что ему нужно: компоненты, хуки, сторы, типы, стили. +## Разделы спецификации + +Спецификация SLM Design состоит из нескольких связанных разделов. Этот обзор даёт общий контекст, а детальные правила описаны дальше: + +- [Слои](#слои) — уровни организации `src/`, направление зависимостей и зона ответственности каждого слоя. +- [Модули](#модули) — границы ответственности, публичный API, типы модулей и отличие модуля от компонента. +- [Сегменты](#сегменты) — внутренние папки модуля (`ui/`, `parts/`, `hooks/`, `types/` и другие) и правила размещения файлов. + +Рекомендуемый порядок чтения: обзор → слои → модули → сегменты. + ## Преимущества ### Вертикальная организация домена @@ -498,7 +508,7 @@ backend-api/ └── index.ts # публичный API ``` -Подробное описание сегментов — в разделе [Сегменты](/architecture/segments). +Подробное описание сегментов — в разделе [Сегменты](#сегменты). ### Публичный API @@ -675,7 +685,7 @@ export const HomeScreen = () => { - Не получает данные самостоятельно, не выбирает источник данных и не композирует данные. - Не содержит бизнес-логику или сценарную логику. -Если UI-сущности нужно что-то за пределами этих ограничений, она должна быть оформлена как модуль. Полная граница описана в разделе [Компонент](/architecture/modules#компонент). +Если UI-сущности нужно что-то за пределами этих ограничений, она должна быть оформлена как модуль. Полная граница описана в разделе [Компонент](#компонент). Корневой файл модуля в `ui/` не размещается. Он лежит в корне модуля: `{module-name}.tsx`. diff --git a/src/screens/home/config/home-screen.config.ts b/src/screens/home/config/home-screen.config.ts index d2684cf..65f0ef4 100644 --- a/src/screens/home/config/home-screen.config.ts +++ b/src/screens/home/config/home-screen.config.ts @@ -8,10 +8,19 @@ export const homeCards = [ cta: 'Открыть →', }, { - title: 'ARCHITECTURE.md', - description: 'Полная версия архитектуры в одном файле', - href: '/ARCHITECTURE.md', - cta: 'Открыть →', + title: 'Скачать', + description: 'Локальная копия спецификации и архив документации.', + actions: [ + { + href: '/ARCHITECTURE.md', + label: 'ARCHITECTURE.md', + }, + { + href: '/slm-design.zip', + label: 'slm-design.zip', + download: true, + }, + ], }, { title: 'Ассистенту', diff --git a/src/screens/home/home.screen.tsx b/src/screens/home/home.screen.tsx index 9bd4a0a..3530f32 100644 --- a/src/screens/home/home.screen.tsx +++ b/src/screens/home/home.screen.tsx @@ -48,7 +48,12 @@ export function HomeScreen() {

{card.description}

{card.actions.map((action) => ( - + {action.label} ))} -- 2.49.1