# Как добавить новый урок или путь обучения

Эта система спроектирована так, чтобы расширение было максимально дешёвым:
**1 правка манифеста + 1 новый файл** — и урок появился везде, где нужно.

---

## Архитектурный обзор (одна минута)

```
DevSecOps/
├── assets/
│   ├── style.css        ← общий стиль сайта (НЕ трогать без причины)
│   ├── lesson.css       ← стиль уроков и путей (прогресс-бары, lesson-nav, аналогии…)
│   ├── layout.js        ← топ-меню + футер на всех страницах
│   ├── lesson-page.js   ← авто-навигация в УРОКЕ (breadcrumbs, прогресс, prev/next)
│   └── path-index.js    ← авто-рендер списка уроков на ИНДЕКСЕ ПУТИ
├── _templates/          ← образцы для копирования
│   ├── lesson.html
│   ├── path-index.html
│   ├── _manifest.example.js
│   └── HOW_TO_ADD_LESSON.md  (этот файл)
├── 01-Roadmap/          ← roadmap по DevOps
├── 02-Linux-Emulator/   ← интерактивный Linux в браузере
├── 03-Lessons/          ← deep dive по темам
│   ├── network-from-zero/    ← пример пути «Сети с нуля»
│   ├── networking-deep/      ← пример пути «HTTPS-запрос deep»
│   └── …
├── 04-Cheatsheets/
└── …
```

### Ключевые понятия

- **Путь обучения (path)** — папка с цепочкой связанных уроков (например, `network-from-zero/`).
- **Манифест (_manifest.js)** — единый источник правды о составе пути. Туда нужно вписать новый урок, и он появится везде.
- **Урок (lesson)** — отдельный HTML-файл со своим содержимым. Подключает манифест и `lesson-page.js`, который сам строит навигацию.

---

## Сценарий 1: Добавить новый УРОК в существующий путь

Допустим, у тебя есть путь `03-Lessons/network-from-zero/` и ты хочешь добавить туда урок 9 «BGP базовый».

### Шаг 1. Открой `_manifest.js` пути

Найди массив `lessons`. Добавь в нужное место (обычно — в конец) новый объект:

```js
{
  id: '09',
  file: '09-bgp-basics.html',
  title: 'BGP — базы',
  desc: 'Как провайдеры рассказывают друг другу о маршрутах',
  icon: '🌍',
}
```

> **ВНИМАНИЕ.** `id` — это короткий уникальный идентификатор урока внутри пути (`'01'`, `'02'`…). Он используется для localStorage-трекера. Не меняй его после публикации, иначе у пользователей сбросится «прочитано».

### Шаг 2. Скопируй шаблон урока

```
cp _templates/lesson.html 03-Lessons/network-from-zero/09-bgp-basics.html
```

(на Windows — просто скопируй через проводник)

### Шаг 3. Открой новый файл, замени плейсхолдеры

- `{{Название урока}}` → «BGP — базы»
- `{{Заголовок урока}}` → «Урок 9 — BGP базовый»
- `{{ID}}` в самой нижней строке (`data-id="{{ID}}"`) → `09`
- Если файл лежит на другой глубине от корня, поправь `../../`-пути в `<link>` и `<script>`. Для `03-Lessons/<path>/` — оставь `../../`.

### Шаг 4. Напиши содержимое

Размещай контент в `<main class="page">` между `<h1>` и `<div data-lesson-footer>`. Используй стилевые классы (`.callout`, `.analogy-box`, `.card`, `pre/code`, `table`).

### Шаг 5. Готово

Открой `index.html` пути — урок появится в списке автоматически. Прев/некст в соседних уроках обновится сам (если ты вставил урок между существующими, замени `id` соответствующим образом).

---

## Сценарий 2: Создать новый ПУТЬ обучения

Допустим, ты хочешь сделать путь «Docker с нуля».

### Шаг 1. Создай папку

```
03-Lessons/docker-from-zero/
```

### Шаг 2. Скопируй шаблон манифеста

```
cp _templates/_manifest.example.js 03-Lessons/docker-from-zero/_manifest.js
```

Открой `_manifest.js`, заполни:
- `id` — уникальный (например, `'docker-from-zero'`)
- `title`, `shortTitle`, `lead`
- `meta` (длительность, уровень)
- `rootBase: '../../'` — так как путь лежит на глубине 2 от корня
- `lessons: [...]` — список планируемых уроков (можно сразу записать названия, файлов ещё нет — добавишь позже)

### Шаг 3. Скопируй шаблон индекса

```
cp _templates/path-index.html 03-Lessons/docker-from-zero/index.html
```

Замени плейсхолдеры. Сохрани.

### Шаг 4. Создай уроки

По шаблону `_templates/lesson.html`, как в сценарии 1.

### Шаг 5. Подсветить путь в общем индексе уроков

Открой `03-Lessons/index.html` и добавь блок `<a class="module-row">` с ссылкой на твой новый путь.

---

## Сценарий 3: Поменять порядок уроков

Просто переставь объекты в массиве `lessons` манифеста. Навигация перестроится сама.

---

## Сценарий 4: Удалить урок

1. Удали объект из `lessons` в `_manifest.js`.
2. Удали HTML-файл урока.
3. Если на него были прямые ссылки из других уроков — поправь их.

> Прогресс пользователя по удалённому уроку останется в его localStorage, но это безвредно — занимает байты.

---

## Сценарий 5: Изменить общую стилистику

- Цвета и базовая типографика → `assets/style.css` (переменные в `:root`).
- Стиль уроков → `assets/lesson.css`.

Все 100+ уроков подхватят изменения автоматически.

---

## Что НЕ нужно делать

- ❌ Не дублируй CSS в `<style>` каждой страницы. Используй `assets/lesson.css` или добавь туда новый класс.
- ❌ Не пиши breadcrumbs / prev-next / прогресс-бар руками. Они генерируются автоматически.
- ❌ Не меняй `id` урока в манифесте после публикации.
- ❌ Не используй абсолютные пути типа `/assets/style.css`. Используй относительные (`../../assets/...`).

---

## Чек-лист «урок готов»

- ☐ Файл назван по схеме `NN-slug.html` (например `03-subnets-cidr.html`)
- ☐ Включает `lesson.css`
- ☐ Включает `_manifest.js` перед `lesson-page.js`
- ☐ `data-id` в `lesson-page.js` совпадает с `id` в манифесте
- ☐ Есть `<div data-lesson-header>` и `<div data-lesson-footer>`
- ☐ Все `<h2>` имеют `id` (для якорей и автогенерации TOC)
- ☐ Есть итоговый `.key-takeaway` или чек-лист
- ☐ Открыл в браузере — навигация работает, прогресс-бар отображается

---

## Шпаргалка по стилевым классам

### Текст и контейнеры
- `.lead` — крупный лид-параграф под заголовком
- `.card` — обычная карточка с рамкой
- `.callout`, `.callout.success`, `.callout.warning`, `.callout.danger`, `.callout.info`
- `.analogy-box` — аналогия с тэгом
- `.key-takeaway` — главная мысль (зелёная)
- `.deep-dive` — «глубже» — карточка с ссылками на смежные темы
- `.term` (внутри обёртки) — глоссарий

### Списки и шаги
- `.step-list` — пронумерованные шаги-блоки
- `.icon-list` — список с иконками

### Сетки
- `.grid-2` — респонсивная сетка из карточек
- `.compare` — таблица сравнения двух колонок (по факту — сетка из card)
- `.principle-grid` — сетка принципов

### Бейджи
- `.badge`, `.badge.accent`, `.badge.success`, `.badge.warning`, `.badge.info`

### Диаграммы
- `.diagram` — обёртка для SVG/ASCII
- `.diagram-caption` — подпись под диаграммой
- `.ascii` — тёмный блок для ASCII-арта
- `.legend` + `.legend .sw` — легенда под диаграммой
- `.mermaid` — блок Mermaid-диаграммы (см. ниже)

---

## Mermaid-диаграммы

Mermaid подключён глобально в `assets/layout.js` и **загружается лениво** — только если на странице есть хоть один блок `.mermaid`. На страницах без диаграмм — ноль overhead.

### Как использовать

Просто положи внутри урока:

```html
<div class="mermaid">
flowchart LR
    A[Юзер] --> B(CDN) --> C{Кэш?}
    C -->|hit| D[edge]
    C -->|miss| E[origin]
</div>
```

Работает также `<pre class="mermaid">...</pre>` и `<pre><code class="language-mermaid">...</code></pre>` — автоматически нормализуются.

### Поддерживаемые типы (всё что нужно для DevOps)

| Тип | Когда использовать |
|---|---|
| `flowchart` | блок-схемы, архитектура, потоки |
| `sequenceDiagram` | взаимодействие сервисов, HTTP-запросы |
| `stateDiagram-v2` | жизненный цикл (pod, заказа, билдa) |
| `erDiagram` | схема БД |
| `gitGraph` | ветки и мерджи |
| `pie` | процентное распределение |
| `gantt` | таймлайны проектов |
| `classDiagram` | объектная модель |
| `journey` | пользовательский путь |

### Когда Mermaid, когда руками SVG

- **Mermaid** — типовая блок-схема, последовательность, ER. Быстро, читаемо в исходнике.
- **SVG руками** — когда нужны точные координаты, нестандартные элементы, иконки, кастомный стиль (как в `networking-deep`).

### Демо

Открой `03-Lessons/mermaid-demo.html` — там 6 типов диаграмм. Если рендерится — всё работает.

---

## Поиск по сайту — не забудь пересобрать индекс

На сайте есть глобальный поиск (кнопка «Поиск» в шапке или `Ctrl/⌘+K`).
Он работает по заранее собранному индексу `assets/search-index.js`.

**После добавления или правки уроков пересобери индекс:**

```bash
node tools/build-search-index.mjs
```

Скрипт сам просканирует все страницы (01-Roadmap, 03-Lessons, 04-Cheatsheets,
05…08, а также главную и osi.html) и перезапишет `assets/search-index.js`.
Ничего вручную в этом файле править не нужно — он автогенерируемый.

### Тесты поиска

```bash
node tests/search.test.mjs         # юнит-тесты ядра поиска
node tests/search-index.test.mjs   # интеграционные тесты по реальному индексу
```

### Проверка схем (SVG)

```bash
node tools/check-svg-bounds.mjs 03-Lessons/твоя-папка
```

Ловит SVG, у которых элементы/подписи вылезают за `viewBox`.
