Compare commits
5 Commits
v3
...
90bf360c06
| Author | SHA1 | Date | |
|---|---|---|---|
| 90bf360c06 | |||
| 5cf0f0f8ba | |||
| 464c709859 | |||
| 64db18917b | |||
| ae103e962e |
@@ -1,6 +1,10 @@
|
|||||||
import { defineConfig } from 'vitepress';
|
import { defineConfig } from 'vitepress';
|
||||||
|
|
||||||
const ruSidebar = [
|
const ruSidebar = [
|
||||||
|
{
|
||||||
|
text: 'Главная',
|
||||||
|
link: '/ru/',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: 'Workflow',
|
text: 'Workflow',
|
||||||
link: '/ru/workflow',
|
link: '/ru/workflow',
|
||||||
@@ -47,6 +51,10 @@ const ruSidebar = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const enSidebar = [
|
const enSidebar = [
|
||||||
|
{
|
||||||
|
text: 'Home',
|
||||||
|
link: '/en/',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: 'Processes',
|
text: 'Processes',
|
||||||
items: [
|
items: [
|
||||||
@@ -137,6 +145,9 @@ export default defineConfig({
|
|||||||
description: 'Стандарты разработки на Next.js + TypeScript с архитектурой SLM',
|
description: 'Стандарты разработки на Next.js + TypeScript с архитектурой SLM',
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
sidebar: ruSidebar,
|
sidebar: ruSidebar,
|
||||||
|
socialLinks: [
|
||||||
|
{ icon: 'github', link: 'https://gromlab.ru/docs/nextjs-style-guide' },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
// Расширенный блок описания для llms.txt — даёт LLM полный
|
// Расширенный блок описания для llms.txt — даёт LLM полный
|
||||||
// технический контекст: стек, методология, охват тем.
|
// технический контекст: стек, методология, охват тем.
|
||||||
@@ -152,6 +163,9 @@ export default defineConfig({
|
|||||||
description: 'Next.js + TypeScript development standards with SLM architecture',
|
description: 'Next.js + TypeScript development standards with SLM architecture',
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
sidebar: enSidebar,
|
sidebar: enSidebar,
|
||||||
|
socialLinks: [
|
||||||
|
{ icon: 'github', link: 'https://gromlab.ru/docs/nextjs-style-guide' },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
llmsBlockquote:
|
llmsBlockquote:
|
||||||
'Frontend development standards for Next.js (App Router) + TypeScript + React projects with SLM architecture (Scoped Layered Module Design — a modular architecture with responsibility layers, where each module contains everything it needs: components, hooks, stores, types, styles).',
|
'Frontend development standards for Next.js (App Router) + TypeScript + React projects with SLM architecture (Scoped Layered Module Design — a modular architecture with responsibility layers, where each module contains everything it needs: components, hooks, stores, types, styles).',
|
||||||
|
|||||||
@@ -15,3 +15,14 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Скрыть root-локаль (лендинг с layout: false) из переключателя языка.
|
||||||
|
* VitePress не даёт исключить root через config — она всегда попадает
|
||||||
|
* в lang-switcher. Идентифицируем по href="/" — другие локали используют
|
||||||
|
* href="/ru/" и href="/en/".
|
||||||
|
*/
|
||||||
|
.VPNavBarTranslations a[href="/"],
|
||||||
|
.VPNavScreenTranslations a[href="/"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|||||||
@@ -185,6 +185,50 @@ title: Название раздела
|
|||||||
- Подсекции внутри `h2` — `h3`.
|
- Подсекции внутри `h2` — `h3`.
|
||||||
- `h4` не используется.
|
- `h4` не используется.
|
||||||
|
|
||||||
|
### Вводный абзац
|
||||||
|
|
||||||
|
Абзац сразу после `h1` отвечает на вопрос «о чём этот раздел?».
|
||||||
|
Он попадает в `llms.txt` и `README.md` архива как краткое описание,
|
||||||
|
поэтому должен быть плотным и без воды.
|
||||||
|
|
||||||
|
**Правила:**
|
||||||
|
|
||||||
|
- Не начинать с «Раздел описывает», «Этот раздел», «В этом разделе»,
|
||||||
|
«Здесь рассмотрено», «В этом документе».
|
||||||
|
- Начинать с подлежащего — самой темы (`Слои SLM:`, `Соглашения об именовании:`).
|
||||||
|
- Двоеточие или тире для перечисления **категорий и областей**, а не
|
||||||
|
конкретных значений из содержимого.
|
||||||
|
- Не дублировать содержимое: если внутри раздела 12 правил —
|
||||||
|
не перечислять их во вводном абзаце.
|
||||||
|
- Не аргументировать («единые правила делают код предсказуемым»).
|
||||||
|
- 1–2 предложения.
|
||||||
|
|
||||||
|
**Проверка:** если при добавлении нового правила/инструмента/раздела
|
||||||
|
вводный абзац придётся править — он слишком конкретный.
|
||||||
|
|
||||||
|
**Хорошо:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Слои SLM: назначение, классификация, направление зависимостей, правила.
|
||||||
|
```
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Базовый стек проекта по областям: UI, архитектура, данные, состояние,
|
||||||
|
локализация, тестирование, стили, генерация кода.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Плохо:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Раздел описывает слои SLM: что такое слой, какие бывают, как между
|
||||||
|
ними направлены зависимости и какие правила действуют на каждом.
|
||||||
|
```
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Этот раздел описывает базовый стек технологий и библиотек, принятый в
|
||||||
|
проекте. React, TypeScript, Next.js, SWR, Zustand, i18next.
|
||||||
|
```
|
||||||
|
|
||||||
### Примеры кода
|
### Примеры кода
|
||||||
|
|
||||||
- Блоки кода с указанием языка: ` ```tsx `, ` ```css `, ` ```bash `, ` ```text `.
|
- Блоки кода с указанием языка: ` ```tsx `, ` ```css `, ` ```bash `, ` ```text `.
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -1,6 +1,17 @@
|
|||||||
# NextJS Style Guide
|
# NextJS Style Guide
|
||||||
|
|
||||||
Rules and standards for NextJS and TypeScript development: architecture, typing, styles, components, API, and infrastructure.
|
Conventions for Next.js project development: application architecture and layers, code structure, module organization, styling, typing, and infrastructure.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
**For AI agents:**
|
||||||
|
|
||||||
|
- [Sections map](https://nextjs-style-guide.gromlab.ru/en/llms.txt) — `llms.txt`, table of contents with links to sections.
|
||||||
|
- [Full text](https://nextjs-style-guide.gromlab.ru/en/llms-full.txt) — `llms-full.txt`, the entire documentation in a single file.
|
||||||
|
|
||||||
|
**For projects:**
|
||||||
|
|
||||||
|
- [Rules archive](https://nextjs-style-guide.gromlab.ru/nextjs-style-guide-en.zip) — `nextjs-style-guide-en.zip`, a set of Markdown files to unpack into `./ai/nextjs-style-guide/` or another project folder.
|
||||||
|
|
||||||
## Documentation Structure
|
## Documentation Structure
|
||||||
|
|
||||||
@@ -26,7 +37,7 @@ Rules and standards for NextJS and TypeScript development: architecture, typing,
|
|||||||
| Section | Answers the question |
|
| Section | Answers the question |
|
||||||
|---------|---------------------|
|
|---------|---------------------|
|
||||||
| Tech Stack | What stack do we use? |
|
| Tech Stack | What stack do we use? |
|
||||||
| Architecture | How are FSD layers, dependencies, and public API structured? |
|
| Architecture | How are SLM layers, dependencies, and public API structured? |
|
||||||
| Code Style | How to format code: indentation, quotes, imports, early return? |
|
| Code Style | How to format code: indentation, quotes, imports, early return? |
|
||||||
| Naming | How to name files, variables, components, hooks? |
|
| Naming | How to name files, variables, components, hooks? |
|
||||||
| Documentation | How to write JSDoc: what to document and what not? |
|
| Documentation | How to write JSDoc: what to document and what not? |
|
||||||
@@ -52,7 +63,4 @@ Rules and standards for NextJS and TypeScript development: architecture, typing,
|
|||||||
| Fonts | _(not filled)_ |
|
| Fonts | _(not filled)_ |
|
||||||
| Localization | _(not filled)_ |
|
| Localization | _(not filled)_ |
|
||||||
|
|
||||||
## For Assistants
|
|
||||||
|
|
||||||
Documentation map with links to all sections ([llmstxt.org](https://llmstxt.org) format):
|
|
||||||
https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/en/llms.txt
|
|
||||||
|
|||||||
16
README_RU.md
16
README_RU.md
@@ -1,11 +1,17 @@
|
|||||||
# NextJS Style Guide
|
# NextJS Style Guide
|
||||||
|
|
||||||
Правила и стандарты разработки на NextJS и TypeScript: архитектура, типизация, стили, компоненты, API и инфраструктурные разделы.
|
Соглашения по разработке Next.js проектов: архитектура и слои приложения, структура кода, организация модулей, стилизация, типизация и инфраструктура.
|
||||||
|
|
||||||
## Для ассистентов
|
## Использование
|
||||||
|
|
||||||
Карта документации со ссылками на все разделы (формат [llmstxt.org](https://llmstxt.org)):
|
**Для AI-агентов:**
|
||||||
https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/ru/llms.txt
|
|
||||||
|
- [Карта разделов](https://nextjs-style-guide.gromlab.ru/ru/llms.txt) — `llms.txt`, оглавление со ссылками на разделы.
|
||||||
|
- [Полный текст](https://nextjs-style-guide.gromlab.ru/ru/llms-full.txt) — `llms-full.txt`, вся документация одним файлом.
|
||||||
|
|
||||||
|
**Для проекта:**
|
||||||
|
|
||||||
|
- [Архив с правилами](https://nextjs-style-guide.gromlab.ru/nextjs-style-guide-ru.zip) — `nextjs-style-guide-ru.zip`, набор Markdown-файлов для распаковки в `./ai/nextjs-style-guide/` или другую папку проекта.
|
||||||
|
|
||||||
## Структура документации
|
## Структура документации
|
||||||
|
|
||||||
@@ -59,3 +65,5 @@ https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/ru/llms.txt
|
|||||||
| Шрифты | _(не заполнен)_ |
|
| Шрифты | _(не заполнен)_ |
|
||||||
| Локализация | _(не заполнен)_ |
|
| Локализация | _(не заполнен)_ |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,17 @@
|
|||||||
# NextJS Style Guide
|
# NextJS Style Guide
|
||||||
|
|
||||||
Rules and standards for NextJS and TypeScript development: architecture, typing, styles, components, API, and infrastructure.
|
Conventions for Next.js project development: application architecture and layers, code structure, module organization, styling, typing, and infrastructure.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
**For AI agents:**
|
||||||
|
|
||||||
|
- [Sections map](https://nextjs-style-guide.gromlab.ru/en/llms.txt) — `llms.txt`, table of contents with links to sections.
|
||||||
|
- [Full text](https://nextjs-style-guide.gromlab.ru/en/llms-full.txt) — `llms-full.txt`, the entire documentation in a single file.
|
||||||
|
|
||||||
|
**For projects:**
|
||||||
|
|
||||||
|
- [Rules archive](https://nextjs-style-guide.gromlab.ru/nextjs-style-guide-en.zip) — `nextjs-style-guide-en.zip`, a set of Markdown files to unpack into `./ai/nextjs-style-guide/` or another project folder.
|
||||||
|
|
||||||
## Documentation Structure
|
## Documentation Structure
|
||||||
|
|
||||||
@@ -26,7 +37,7 @@ Rules and standards for NextJS and TypeScript development: architecture, typing,
|
|||||||
| Section | Answers the question |
|
| Section | Answers the question |
|
||||||
|---------|---------------------|
|
|---------|---------------------|
|
||||||
| Tech Stack | What stack do we use? |
|
| Tech Stack | What stack do we use? |
|
||||||
| Architecture | How are FSD layers, dependencies, and public API structured? |
|
| Architecture | How are SLM layers, dependencies, and public API structured? |
|
||||||
| Code Style | How to format code: indentation, quotes, imports, early return? |
|
| Code Style | How to format code: indentation, quotes, imports, early return? |
|
||||||
| Naming | How to name files, variables, components, hooks? |
|
| Naming | How to name files, variables, components, hooks? |
|
||||||
| Documentation | How to write JSDoc: what to document and what not? |
|
| Documentation | How to write JSDoc: what to document and what not? |
|
||||||
@@ -52,7 +63,4 @@ Rules and standards for NextJS and TypeScript development: architecture, typing,
|
|||||||
| Fonts | _(not filled)_ |
|
| Fonts | _(not filled)_ |
|
||||||
| Localization | _(not filled)_ |
|
| Localization | _(not filled)_ |
|
||||||
|
|
||||||
## For Assistants
|
|
||||||
|
|
||||||
Documentation map with links to all sections ([llmstxt.org](https://llmstxt.org) format):
|
|
||||||
https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/en/llms.txt
|
|
||||||
|
|||||||
155
docs/index.md
155
docs/index.md
@@ -14,9 +14,10 @@ const buildVersion = __BUILD_VERSION__
|
|||||||
|
|
||||||
const dict = {
|
const dict = {
|
||||||
ru: {
|
ru: {
|
||||||
tagline: 'Готовые соглашения по архитектуре, коду, компонентам и инфраструктуре для Next.js + TypeScript-проектов — чтобы команда писала одинаково, а новые разработчики включались в проект быстрее.',
|
tagline: 'Соглашения по разработке Next.js проектов: архитектура и слои приложения, структура кода, организация модулей, стилизация, типизация и инфраструктура.',
|
||||||
langLabel: 'Язык',
|
langLabel: 'Язык',
|
||||||
themeLabel: 'Тема',
|
themeLabel: 'Тема',
|
||||||
|
repoLabel: 'Репозиторий',
|
||||||
themes: { auto: 'Авто', light: 'Светлая', dark: 'Тёмная' },
|
themes: { auto: 'Авто', light: 'Светлая', dark: 'Тёмная' },
|
||||||
cards: {
|
cards: {
|
||||||
docs: {
|
docs: {
|
||||||
@@ -28,8 +29,10 @@ const dict = {
|
|||||||
ai: {
|
ai: {
|
||||||
title: 'Ассистенту',
|
title: 'Ассистенту',
|
||||||
desc: 'Карта документации в формате llms.txt для AI-агентов.',
|
desc: 'Карта документации в формате llms.txt для AI-агентов.',
|
||||||
href: './ru/llms.txt',
|
buttons: [
|
||||||
cta: 'Открыть',
|
{ label: 'llms.txt', href: './ru/llms.txt' },
|
||||||
|
{ label: 'llms-full.txt', href: './ru/llms-full.txt' },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
zip: {
|
zip: {
|
||||||
title: 'Скачать правила',
|
title: 'Скачать правила',
|
||||||
@@ -40,9 +43,10 @@ const dict = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
tagline: 'Ready-made standards for architecture, code, components, and infrastructure in Next.js + TypeScript projects — so your team writes consistently and new developers ramp up faster.',
|
tagline: 'Conventions for Next.js project development: application architecture and layers, code structure, module organization, styling, typing, and infrastructure.',
|
||||||
langLabel: 'Language',
|
langLabel: 'Language',
|
||||||
themeLabel: 'Theme',
|
themeLabel: 'Theme',
|
||||||
|
repoLabel: 'Repository',
|
||||||
themes: { auto: 'Auto', light: 'Light', dark: 'Dark' },
|
themes: { auto: 'Auto', light: 'Light', dark: 'Dark' },
|
||||||
cards: {
|
cards: {
|
||||||
docs: {
|
docs: {
|
||||||
@@ -55,9 +59,11 @@ const dict = {
|
|||||||
ai: {
|
ai: {
|
||||||
title: 'For Assistant',
|
title: 'For Assistant',
|
||||||
desc: 'Documentation map in llms.txt format for AI agents.',
|
desc: 'Documentation map in llms.txt format for AI agents.',
|
||||||
href: '#',
|
|
||||||
cta: 'Open',
|
|
||||||
badge: 'in development',
|
badge: 'in development',
|
||||||
|
buttons: [
|
||||||
|
{ label: 'llms.txt', href: '#' },
|
||||||
|
{ label: 'llms-full.txt', href: '#' },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
zip: {
|
zip: {
|
||||||
title: 'Download rules',
|
title: 'Download rules',
|
||||||
@@ -120,6 +126,17 @@ function toggleTheme(value) {
|
|||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<p class="landing__tagline">{{ t.tagline }}</p>
|
<p class="landing__tagline">{{ t.tagline }}</p>
|
||||||
<div class="landing__controls">
|
<div class="landing__controls">
|
||||||
|
<a
|
||||||
|
class="landing__repo"
|
||||||
|
href="https://gromlab.ru/docs/nextjs-style-guide"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||||
|
<path d="M12 .3a12 12 0 0 0-3.8 23.38c.6.12.83-.26.83-.57L9 21.07c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.08-.74.09-.73.09-.73 1.2.09 1.83 1.24 1.83 1.24 1.08 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18a4.65 4.65 0 0 1 1.23 3.22c0 4.61-2.8 5.63-5.48 5.92.42.36.81 1.1.81 2.22l-.01 3.29c0 .31.2.69.82.57A12 12 0 0 0 12 .3Z"/>
|
||||||
|
</svg>
|
||||||
|
<span>{{ t.repoLabel }}</span>
|
||||||
|
</a>
|
||||||
<div class="seg" role="group" :aria-label="t.langLabel">
|
<div class="seg" role="group" :aria-label="t.langLabel">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -164,9 +181,31 @@ function toggleTheme(value) {
|
|||||||
|
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<section class="landing__cards">
|
<section class="landing__cards">
|
||||||
|
<template v-for="key in ['docs', 'ai', 'zip']" :key="key">
|
||||||
|
<div
|
||||||
|
v-if="t.cards[key].buttons"
|
||||||
|
class="landing__card landing__card--multi"
|
||||||
|
:class="{ 'landing__card--soon': t.cards[key].badge }"
|
||||||
|
:aria-disabled="t.cards[key].badge ? 'true' : null"
|
||||||
|
>
|
||||||
|
<h3>
|
||||||
|
{{ t.cards[key].title }}
|
||||||
|
<span v-if="t.cards[key].badge" class="landing__badge">{{ t.cards[key].badge }}</span>
|
||||||
|
</h3>
|
||||||
|
<p>{{ t.cards[key].desc }}</p>
|
||||||
|
<div class="landing__buttons">
|
||||||
<a
|
<a
|
||||||
v-for="key in ['docs', 'ai', 'zip']"
|
v-for="btn in t.cards[key].buttons"
|
||||||
:key="key"
|
:key="btn.label"
|
||||||
|
class="landing__button"
|
||||||
|
:href="btn.href"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>{{ btn.label }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
v-else
|
||||||
class="landing__card"
|
class="landing__card"
|
||||||
:class="{ 'landing__card--soon': t.cards[key].badge }"
|
:class="{ 'landing__card--soon': t.cards[key].badge }"
|
||||||
:href="t.cards[key].href"
|
:href="t.cards[key].href"
|
||||||
@@ -179,6 +218,7 @@ function toggleTheme(value) {
|
|||||||
<p>{{ t.cards[key].desc }}</p>
|
<p>{{ t.cards[key].desc }}</p>
|
||||||
<span class="landing__cta">{{ t.cards[key].cta }} →</span>
|
<span class="landing__cta">{{ t.cards[key].cta }} →</span>
|
||||||
</a>
|
</a>
|
||||||
|
</template>
|
||||||
</section>
|
</section>
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
|
|
||||||
@@ -207,6 +247,35 @@ function toggleTheme(value) {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.landing__controls > * {
|
||||||
|
height: 36px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__repo {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 0 14px;
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--vp-c-bg-soft);
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.15s, border-color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__repo:hover {
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
border-color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__repo svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.seg {
|
.seg {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
@@ -332,6 +401,33 @@ function toggleTheme(value) {
|
|||||||
color: var(--vp-c-brand-1);
|
color: var(--vp-c-brand-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.landing__buttons {
|
||||||
|
margin-top: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__button {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: var(--vp-font-family-mono, monospace);
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
background: var(--vp-c-bg);
|
||||||
|
border: 1px solid var(--vp-c-divider);
|
||||||
|
border-radius: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: border-color 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__button:hover {
|
||||||
|
border-color: var(--vp-c-brand-1);
|
||||||
|
color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
.landing__version {
|
.landing__version {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 24px 0 0;
|
margin: 24px 0 0;
|
||||||
@@ -356,17 +452,56 @@ function toggleTheme(value) {
|
|||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.landing {
|
.landing {
|
||||||
padding: 16px 16px 48px;
|
padding: 48px 20px 56px;
|
||||||
gap: 32px;
|
gap: 40px;
|
||||||
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
.landing__title {
|
.landing__title {
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
}
|
}
|
||||||
|
.landing__tagline {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
.landing__cards {
|
.landing__cards {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
gap: 16px;
|
||||||
}
|
}
|
||||||
.landing__controls {
|
.landing__controls {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
margin-top: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.landing {
|
||||||
|
padding: 44px 16px 48px;
|
||||||
|
gap: 36px;
|
||||||
|
}
|
||||||
|
.landing__title {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
.landing__tagline {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.landing__controls {
|
||||||
|
margin-top: 32px;
|
||||||
|
}
|
||||||
|
/* Репозиторий — только иконка, без текста, чтобы все контролы влезли в строку */
|
||||||
|
.landing__repo {
|
||||||
|
width: 36px;
|
||||||
|
padding: 0;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.landing__repo span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.seg__btn {
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.landing__card {
|
||||||
|
padding: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Структура проекта
|
|||||||
|
|
||||||
# Структура проекта
|
# Структура проекта
|
||||||
|
|
||||||
Раздел описывает расположение файлов и папок в проекте Next.js (App Router).
|
Файловая организация Next.js-проекта по архитектуре SLM.
|
||||||
|
|
||||||
## Корень репозитория
|
## Корень репозитория
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Стили
|
|||||||
|
|
||||||
# Стили
|
# Стили
|
||||||
|
|
||||||
Раздел описывает правила написания CSS: PostCSS Modules, вложенность, медиа-запросы, переменные, форматирование.
|
Правила написания CSS: PostCSS Modules, форматирование, переменные.
|
||||||
|
|
||||||
## Общие правила
|
## Общие правила
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Архитектура
|
title: Архитектура
|
||||||
description: "Раздел описывает архитектуру проекта: из каких слоёв состоит приложение, как организован код внутри слоёв и какие правила управляют зависимостями."
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# SLM Design
|
# SLM Design
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Слои
|
|||||||
|
|
||||||
# Слои
|
# Слои
|
||||||
|
|
||||||
Раздел описывает слои SLM: что такое слой, какие бывают, как между ними направлены зависимости и какие правила действуют на каждом.
|
Слои SLM: назначение, классификация, направление зависимостей, правила.
|
||||||
|
|
||||||
## Определение
|
## Определение
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Модули
|
|||||||
|
|
||||||
# Модули
|
# Модули
|
||||||
|
|
||||||
Раздел описывает модули SLM: что такое модуль, из чего он состоит и как взаимодействует с остальным кодом.
|
Модули SLM: состав, границы, взаимодействие с остальным кодом.
|
||||||
|
|
||||||
## Определение
|
## Определение
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Сегменты
|
|||||||
|
|
||||||
# Сегменты
|
# Сегменты
|
||||||
|
|
||||||
Раздел описывает сегменты SLM: что такое сегмент, какие бывают и что в каждом из них лежит.
|
Сегменты SLM: типы, назначение, что лежит внутри каждого.
|
||||||
|
|
||||||
## Определение
|
## Определение
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Стиль кода
|
|||||||
|
|
||||||
# Стиль кода
|
# Стиль кода
|
||||||
|
|
||||||
Раздел описывает единые правила оформления кода: отступы, переносы, кавычки, порядок импортов и базовую читаемость.
|
Единые правила оформления кода: форматирование, импорты, читаемость.
|
||||||
|
|
||||||
## Отступы
|
## Отступы
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ title: Документирование
|
|||||||
|
|
||||||
# Документирование
|
# Документирование
|
||||||
|
|
||||||
Этот раздел описывает правила документирования кода: когда и как писать
|
Правила документирования кода: что и когда документировать через JSDoc.
|
||||||
комментарии к компонентам, функциям, типам и интерфейсам.
|
|
||||||
|
|
||||||
## Общие правила
|
## Общие правила
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Именование
|
|||||||
|
|
||||||
# Именование
|
# Именование
|
||||||
|
|
||||||
Этот раздел описывает соглашения об именовании в проекте. Единые правила делают код предсказуемым и упрощают навигацию по проекту.
|
Соглашения об именовании в коде: что и как называть.
|
||||||
|
|
||||||
## Базовые правила
|
## Базовые правила
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Технологии и библиотеки
|
|||||||
|
|
||||||
# Технологии и библиотеки
|
# Технологии и библиотеки
|
||||||
|
|
||||||
Этот раздел описывает базовый стек технологий и библиотек, принятый в проекте.
|
Базовый стек проекта по областям: UI, архитектура, данные, состояние, локализация, тестирование, стили, генерация кода.
|
||||||
|
|
||||||
## Что используем
|
## Что используем
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Типизация
|
|||||||
|
|
||||||
# Типизация
|
# Типизация
|
||||||
|
|
||||||
Этот раздел описывает правила типизации: как типизировать компоненты, функции и работу с `any`/`unknown`.
|
Правила типизации в TypeScript: общие принципы и работа с динамическими типами.
|
||||||
|
|
||||||
## Общие правила
|
## Общие правила
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
# NextJS Style Guide
|
# NextJS Style Guide
|
||||||
|
|
||||||
Правила и стандарты разработки на NextJS и TypeScript: архитектура, типизация, стили, компоненты, API и инфраструктурные разделы.
|
Соглашения по разработке Next.js проектов: архитектура и слои приложения, структура кода, организация модулей, стилизация, типизация и инфраструктура.
|
||||||
|
|
||||||
## Для ассистентов
|
## Использование
|
||||||
|
|
||||||
Карта документации со ссылками на все разделы (формат [llmstxt.org](https://llmstxt.org)):
|
**Для AI-агентов:**
|
||||||
https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/ru/llms.txt
|
|
||||||
|
- [Карта разделов](https://nextjs-style-guide.gromlab.ru/ru/llms.txt) — `llms.txt`, оглавление со ссылками на разделы.
|
||||||
|
- [Полный текст](https://nextjs-style-guide.gromlab.ru/ru/llms-full.txt) — `llms-full.txt`, вся документация одним файлом.
|
||||||
|
|
||||||
|
**Для проекта:**
|
||||||
|
|
||||||
|
- [Архив с правилами](https://nextjs-style-guide.gromlab.ru/nextjs-style-guide-ru.zip) — `nextjs-style-guide-ru.zip`, набор Markdown-файлов для распаковки в `./ai/nextjs-style-guide/` или другую папку проекта.
|
||||||
|
|
||||||
## Структура документации
|
## Структура документации
|
||||||
|
|
||||||
@@ -59,3 +65,5 @@ https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/ru/llms.txt
|
|||||||
| Шрифты | _(не заполнен)_ |
|
| Шрифты | _(не заполнен)_ |
|
||||||
| Локализация | _(не заполнен)_ |
|
| Локализация | _(не заполнен)_ |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
244
generate-llms.ts
244
generate-llms.ts
@@ -301,19 +301,173 @@ const copyMdFiles = (lang: Lang): void => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Собрать `nextjs-style-guide-{lang}.zip` со всеми `.md` локали и `VERSION`.
|
* Преобразовать sidebar `link` в относительный путь файла внутри архива
|
||||||
* Внутри архива — единая папка `nextjs-style-guide/`.
|
* (от корня папки `nextjs-style-guide/`). Это путь, по которому файл лежит
|
||||||
|
* в распакованной папке, без расширения добавляется `.md`.
|
||||||
|
*/
|
||||||
|
const linkToArchiveRel = (link: string, lang: Lang): string => {
|
||||||
|
const prefix = `/${lang}/`;
|
||||||
|
let rel = link.startsWith(prefix) ? link.slice(prefix.length) : link.replace(/^\//, '');
|
||||||
|
if (rel === '' || rel.endsWith('/')) {
|
||||||
|
rel += 'index.md';
|
||||||
|
} else {
|
||||||
|
rel += '.md';
|
||||||
|
}
|
||||||
|
return rel;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Заменить во всех `.md` архива ссылки `[text](/ru/foo)` на относительные
|
||||||
|
* пути от расположения файла. Без этого внутренние ссылки в распакованной
|
||||||
|
* папке не работают.
|
||||||
|
*/
|
||||||
|
const transformLinksInDir = (rootDir: string, lang: Lang): void => {
|
||||||
|
const linkRe = /\]\(\/([a-z]{2})\/([^)\s#]*)(#[^)]*)?\)/g;
|
||||||
|
|
||||||
|
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, urlLang, route, hash = '') => {
|
||||||
|
// Ссылки на другую локаль не трогаем — её в архиве нет.
|
||||||
|
if (urlLang !== lang) return match;
|
||||||
|
|
||||||
|
const fakeLink = `/${urlLang}/${route}${route.endsWith('/') ? '' : ''}`;
|
||||||
|
const targetRel = linkToArchiveRel(fakeLink, lang);
|
||||||
|
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 = (lang: Lang, rootDir: string): void => {
|
||||||
|
const cfg = config as unknown as {
|
||||||
|
title: string;
|
||||||
|
locales: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
description?: string;
|
||||||
|
llmsBlockquote?: string;
|
||||||
|
llmsContext?: string;
|
||||||
|
themeConfig?: { sidebar?: SidebarItem[] };
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const locale = cfg.locales[lang];
|
||||||
|
const sidebar = locale?.themeConfig?.sidebar;
|
||||||
|
if (!sidebar) return;
|
||||||
|
|
||||||
|
const blockquote = locale.llmsBlockquote ?? locale.description ?? '';
|
||||||
|
const context = locale.llmsContext;
|
||||||
|
const entries = flattenSidebar(sidebar).filter(
|
||||||
|
// «Главная» из sidebar — это страница локали для веба, в архиве не нужна.
|
||||||
|
(e) => !(e.section === 'Главная' || e.section === 'Home'),
|
||||||
|
);
|
||||||
|
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('');
|
||||||
|
}
|
||||||
|
|
||||||
|
const heading = lang === 'ru' ? 'Содержание' : 'Contents';
|
||||||
|
lines.push(`## ${heading}`);
|
||||||
|
lines.push('');
|
||||||
|
|
||||||
|
for (const [section, items] of grouped) {
|
||||||
|
lines.push(`### ${section}`);
|
||||||
|
lines.push('');
|
||||||
|
for (const entry of items) {
|
||||||
|
const targetRel = './' + linkToArchiveRel(entry.link, lang);
|
||||||
|
const filePath = path.join(rootDir, linkToArchiveRel(entry.link, lang));
|
||||||
|
|
||||||
|
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-{lang}.zip`. Внутри архива — единая папка
|
||||||
|
* `nextjs-style-guide/` с `.md`-файлами локали, README-точкой входа,
|
||||||
|
* `llms-full.txt` и `VERSION`. Внутренние ссылки в `.md` преобразуются
|
||||||
|
* в относительные.
|
||||||
*
|
*
|
||||||
* `llms.txt` в архив не кладём: его ссылки указывают на сайт и локально
|
* Веб-`index.md` локали из архива удаляется — его роль выполняет README.md.
|
||||||
* не работают. Структура папки сама по себе является картой документации.
|
|
||||||
*/
|
*/
|
||||||
const buildZip = (lang: Lang): void => {
|
const buildZip = (lang: Lang): void => {
|
||||||
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'nsg-'));
|
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'nsg-'));
|
||||||
const stage = path.join(tmpRoot, 'nextjs-style-guide');
|
const stage = path.join(tmpRoot, 'nextjs-style-guide');
|
||||||
fs.mkdirSync(stage, { recursive: true });
|
fs.mkdirSync(stage, { recursive: true });
|
||||||
|
|
||||||
|
// 1. Копируем все .md локали в staging.
|
||||||
copyDirSync(path.join('docs', lang), stage, (name) => name.endsWith('.md'));
|
copyDirSync(path.join('docs', lang), stage, (name) => name.endsWith('.md'));
|
||||||
|
|
||||||
|
// 2. Удаляем веб-index.md локали — в архиве он избыточен.
|
||||||
|
const indexPath = path.join(stage, 'index.md');
|
||||||
|
if (fs.existsSync(indexPath)) fs.unlinkSync(indexPath);
|
||||||
|
|
||||||
|
// 3. Преобразуем абсолютные ссылки `/ru/...` в относительные.
|
||||||
|
transformLinksInDir(stage, lang);
|
||||||
|
|
||||||
|
// 4. Генерируем точку входа README.md.
|
||||||
|
buildArchiveReadme(lang, stage);
|
||||||
|
|
||||||
|
// 5. Кладём llms-full.txt — удобно для одноразового чтения LLM.
|
||||||
|
const llmsFullSrc = path.join(PUBLIC_DIR, lang, 'llms-full.txt');
|
||||||
|
if (fs.existsSync(llmsFullSrc)) {
|
||||||
|
fs.copyFileSync(llmsFullSrc, path.join(stage, 'llms-full.txt'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Метаинформация сборки.
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(stage, 'VERSION'),
|
path.join(stage, 'VERSION'),
|
||||||
`${VERSION}\n${BUILD_DATE}\n`,
|
`${VERSION}\n${BUILD_DATE}\n`,
|
||||||
@@ -333,6 +487,84 @@ const buildZip = (lang: Lang): void => {
|
|||||||
console.log(`${outFile} создан (${VERSION})`);
|
console.log(`${outFile} создан (${VERSION})`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Удалить YAML frontmatter из исходника `.md`. */
|
||||||
|
const stripFrontmatter = (content: string): string =>
|
||||||
|
content.replace(/^---\n[\s\S]*?\n---\n*/, '');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сдвинуть уровень заголовков на 1 вниз (h1→h2, h2→h3, ...).
|
||||||
|
* Игнорирует строки внутри блоков кода.
|
||||||
|
*/
|
||||||
|
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` — все страницы локали в одном файле.
|
||||||
|
* Порядок страниц повторяет порядок в sidebar.
|
||||||
|
*/
|
||||||
|
const buildLlmsFull = (lang: Lang): void => {
|
||||||
|
const cfg = config as unknown as {
|
||||||
|
title: string;
|
||||||
|
locales: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
description?: string;
|
||||||
|
llmsBlockquote?: string;
|
||||||
|
llmsContext?: string;
|
||||||
|
themeConfig?: { sidebar?: SidebarItem[] };
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const locale = cfg.locales[lang];
|
||||||
|
const sidebar = locale?.themeConfig?.sidebar;
|
||||||
|
if (!sidebar) return;
|
||||||
|
|
||||||
|
const entries = flattenSidebar(sidebar);
|
||||||
|
const blockquote = locale.llmsBlockquote ?? locale.description ?? '';
|
||||||
|
|
||||||
|
const parts: string[] = [];
|
||||||
|
parts.push(`# ${cfg.title}`);
|
||||||
|
parts.push('');
|
||||||
|
if (blockquote) parts.push(`> ${blockquote}`);
|
||||||
|
if (locale.llmsContext) {
|
||||||
|
parts.push('');
|
||||||
|
parts.push(locale.llmsContext);
|
||||||
|
}
|
||||||
|
parts.push('');
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const filePath = linkToFilePath(entry.link, lang);
|
||||||
|
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('');
|
||||||
|
}
|
||||||
|
|
||||||
|
const outDir = path.join(PUBLIC_DIR, lang);
|
||||||
|
fs.mkdirSync(outDir, { recursive: true });
|
||||||
|
const outFile = path.join(outDir, 'llms-full.txt');
|
||||||
|
fs.writeFileSync(outFile, parts.join('\n'), 'utf8');
|
||||||
|
console.log(`${outFile} создан`);
|
||||||
|
};
|
||||||
|
|
||||||
/** Манифест сборки — для лендинга и внешних потребителей. */
|
/** Манифест сборки — для лендинга и внешних потребителей. */
|
||||||
const writeManifest = (): void => {
|
const writeManifest = (): void => {
|
||||||
const manifest = {
|
const manifest = {
|
||||||
@@ -341,10 +573,12 @@ const writeManifest = (): void => {
|
|||||||
languages: {
|
languages: {
|
||||||
ru: {
|
ru: {
|
||||||
llms: '/ru/llms.txt',
|
llms: '/ru/llms.txt',
|
||||||
|
llmsFull: '/ru/llms-full.txt',
|
||||||
zip: '/nextjs-style-guide-ru.zip',
|
zip: '/nextjs-style-guide-ru.zip',
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
llms: '/en/llms.txt',
|
llms: '/en/llms.txt',
|
||||||
|
llmsFull: '/en/llms-full.txt',
|
||||||
zip: '/nextjs-style-guide-en.zip',
|
zip: '/nextjs-style-guide-en.zip',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -373,6 +607,8 @@ const buildReadme = (lang: Lang, outFile: string): void => {
|
|||||||
|
|
||||||
buildLlms('ru');
|
buildLlms('ru');
|
||||||
buildLlms('en');
|
buildLlms('en');
|
||||||
|
buildLlmsFull('ru');
|
||||||
|
buildLlmsFull('en');
|
||||||
buildRootIndex();
|
buildRootIndex();
|
||||||
copyMdFiles('ru');
|
copyMdFiles('ru');
|
||||||
copyMdFiles('en');
|
copyMdFiles('en');
|
||||||
|
|||||||
Reference in New Issue
Block a user