Initial commit: LangChain evolution tutorial deck (132 slides)

- Cover, TOC, 5 dividers, 3 recap slides
- 5 sections (chains, langgraph, deepagents, openswe, ecosystem)
- design-system.js with theme tokens + 9 helper functions
- research/: timeline + sources + per-tech notes
- final-compile.js + merge.js for rebuild pipeline
- output/: langchain-evolution.pptx (2.3 MB) + langchain-evolution.pdf (1.1 MB) + 7 sample previews
This commit is contained in:
2026-06-22 11:29:03 +03:00
parent ed5b5c91bf
commit 75601988c2
220 changed files with 13069 additions and 3 deletions
+149
View File
@@ -0,0 +1,149 @@
# design-system.md
Гайд по `lc-evo-deck/design-system.js` для тех, кто собирает слайды.
## Что внутри
`design-system.js` экспортирует единый объект с тремя слоями:
| Слой | Что лежит |
| ---------- | --------------------------------------------------------------- |
| `palette` | Цвета: фон, текст, акценты, код, состояния |
| `fonts` | `code`, `ui`, `fallback` (Arial для кириллицы) |
| `sizes` | Шкала шрифтов: `h1` ... `caption`, `eyebrow` |
| `spacing` | Отступы: `page`, `card_pad`, `gap` |
| `layouts` | Константы 16:9: `HEADER_Y`, `CONTENT_TOP`, `CONTENT_BOTTOM`, `FOOTER_Y` |
| `theme` | Все перечисленное выше в одном объекте (удобно пробрасывать) |
| `helpers` | Готовые функции для сборки слайда |
Импорт:
```js
const ds = require('./design-system');
const { theme, helpers, layouts } = ds;
```
## Геометрия слайда (16:9, дюймы)
```
y=0.00 +-----------------------------------------------+
| HEADER_Y = 0.4 |
| eyebrow (10pt, accent) |
y=1.25 | --- hairline --- |
| CONTENT_TOP = 1.4 <-- начинай контент тут |
| |
| контент |
| |
y=5.05 | CONTENT_BOTTOM = 5.05 |
| FOOTER_Y = 5.25 <-- page number, source |
y=5.625 +-----------------------------------------------+
x=0.5 x=9.5
^ отступ `spacing.page` (0.5 дюйма) с обеих сторон
```
## Минимальный слайд
```js
const pptxgen = require('pptxgenjs');
const ds = require('./design-system');
const { theme, helpers, layouts } = ds;
const pres = new pptxgen();
pres.layout = 'LAYOUT_16x9';
const slide = pres.addSlide();
helpers.slideBase(slide, pres, theme);
helpers.addHeader(slide, pres, theme, {
section: 'Stage 2: Chains',
sectionNumber: 2,
title: 'LCEL: composable expressions',
eyebrow: 'STAGE 2',
});
helpers.addPageNumber(slide, pres, theme, 1);
await pres.writeFile({ fileName: 'lc-evolution.pptx' });
```
## Какой layout для какого случая
| Слайд | Что использовать |
| ------------------------------ | --------------------------------------------------------- |
| Титул раздела / stage divider | `helpers.addSectionDivider` (большая цифра + заголовок) |
| Текст + код | `addHeader` + `addCodeBlock` слева, `addCallout` справа |
| Сравнение двух подходов | `addProsCons` (две колонки, + и -) |
| Цитата / важное замечание | `addCallout` с `kind: 'info' | 'warning' | 'success' | 'danger'` |
| Код с акцентом на строке | `addCodeBlockWithHighlight` + `lines: [3, 4]` |
| Источник внизу | `addSourceLine` |
| Любой слайд | `addPageNumber` в правом нижнем углу |
## Helper-функции -- короткая справка
### `slideBase(slide, pres, theme)`
Закрашивает фон `bg.primary`. Вызывай первым на каждом слайде.
### `addHeader(slide, pres, theme, opts)`
- `opts.eyebrow` -- маленький caps-ярлык сверху (например `STAGE 2: CHAINS`)
- `opts.section` -- альтернатива eyebrow
- `opts.sectionNumber` -- крупная цифра справа (необязательно)
- `opts.title` -- h1
### `addCodeBlock(slide, pres, theme, opts)`
- `opts.code` -- строка кода (`\n` для переносов)
- `opts.filePath` + `opts.startLine` -- подпись `// path/to/file.py:1-12`
- `opts.highlightLines` -- массив 1-based номеров строк, которые подсветить
- Если строк больше, чем влезает по высоте, внизу появится желтая плашка
`// note: snippet has N lines, card fits ~M` -- уменьши `fontSize` или
разбей сниппет.
### `addCodeBlockWithHighlight(slide, pres, theme, opts)`
То же самое, но принимает `lines: [3, 4]` как алиас для `highlightLines`.
### `addCallout(slide, pres, theme, opts)`
- `opts.kind` -- `info` | `warning` | `success` | `danger`
- `opts.title` -- необязательный заголовок внутри плашки
- `opts.text` -- основной текст
### `addProsCons(slide, pres, theme, opts)`
- `opts.pros` -- массив строк
- `opts.cons` -- массив строк
- Плюсы слева (зелёная рамка), минусы справа (красная).
### `addPageNumber(slide, pres, theme, n)`
Правый нижний угол, монохромный caption.
### `addSectionDivider(slide, pres, theme, opts)`
- `opts.number` -- крупная цифра слева
- `opts.title` -- заголовок справа
- `opts.eyebrow` -- необязательный caps-ярлык
- `opts.intro` -- абзац под заголовком
### `addSourceLine(slide, pres, theme, opts)`
- `opts.source` -- URL или короткая ссылка
- По умолчанию `x=0.5, y=5.30, w=7.0`
### `highlightPython(code)` (опционально)
Если на машине стоит `pygmentize` (из пакета `pygments`), функция вернет
массив `{ text, color }` токенов. Если бинарника нет -- вернется один токен
с дефолтным цветом и весь код отрисуется моноширинно. Используй, когда
нужна попроцедурная подсветка поверх `addCodeBlock`.
## Правила
1. Не вставляй em-dash (`--`) и en-dash (`-`) -- заменяй на `--` и `-`.
2. Не используй Unicode-кавычки -- только ASCII `"` и `'`.
3. Не используй `...` -- заменяй на `...`.
4. Шрифты -- всегда через `helpers.withFallback(name)`, чтобы Arial был
гарантированным фолбэком.
5. Цвета бери из `palette.*` -- не хардкодь hex в слайдах.
6. Геометрия -- через `layouts.*` константы.
7. Любой новый слайд начинается с `slideBase(...)`.
## Частые ошибки
| Симптом | Причина | Фикс |
| -------------------------------------- | ------------------------------------ | --------------------------------------------------- |
| Шрифт Arial вместо JetBrains Mono | PowerPoint не нашел шрифт | Установи `JetBrains Mono` в систему |
| Кириллица в коде рендерится квадратами | Нет фолбэка | Используй `helpers.withFallback(t.fonts.code)` |
| Код вылезает за карточку | Слишком много строк | Уменьши `sizes.code` или укороти сниппет |
| Header и контент перекрываются | Контент начинается выше `CONTENT_TOP`| Подними `y` до `layouts.CONTENT_TOP` |
| Плашка `note: snippet has N lines` | Сниппет не помещается | Разбей на 2 карточки или уменьши `sizes.code` |